# LibreDesk 本地实例(yehwang-ai) 按官方文档 [docs.libredesk.io/getting-started/installation](https://docs.libredesk.io/getting-started/installation) 的 Docker 方式部署的独立实例, 与本机 `crm-new` 项目里那套 LibreDesk 完全隔离(独立容器、独立数据卷、独立端口)。 ## 两套环境 | 环境 | 访问地址 | 位置 | 说明 | | --- | --- | --- | --- | | 开发(本机) | https://192.168.31.61:9443 | 本机 `libredesk/` | 自签证书 TLS 容器,日常开发/验证 | | 测试(测试服) | https://wangliang-crm.dev.gaia888.com | `47.76.223.252:/data/dev/wangliang/libredesk` | 共享测试,宿主 nginx 提供 TLS | ### 测试服实例要点(2026-10-29 迁移部署) - 目标机 ARM64,镜像 `libredesk/libredesk:v2.9.1`(多架构,自动取 arm64)。 - **无 tls 容器**:宿主 nginx 已有 `wangliang-crm.dev.gaia888.com → 127.0.0.1:9000` 的 server 块,TLS 由 letsencrypt 证书提供。 - 端口:app `9000`(`0.0.0.0`)、db `127.0.0.1:5440`、redis `127.0.0.1:6390`、bridge-tools `127.0.0.1:4100`。 - bridge-tools 额外接入 `spug-net`,RPC 全部指向 wangliang 空间:`jsonrpc://wangliang-dev:9503/9505/9509/9506`。 - 数据从本机迁移(`pg_dump` 恢复),`encryption_key` 与本机一致;`app.root_url` 已改为测试服域名。 - 旧 `crm-ai`(`crmnew-*`)栈已下线,数据卷 `crm-new_pg-data` / `crm-new_redis-data` / `crm-new_twenty-data` 保留。 - 运维:`ssh yw-dev` 后 `cd /data/dev/wangliang/libredesk && docker compose ps|logs|restart`。 - 测试服版 compose 见 `deploy/testspace/docker-compose.yml`(与本仓库 `docker-compose.yml` 的差异即上述几项); 实例配置变更(trusted_domains / widget 文案 / AI 问候规则)见 [docs/testspace-config-changes.md](docs/testspace-config-changes.md)。 ## 访问(本机开发实例) | 项 | 值 | | --- | --- | | 后台地址 | **https://192.168.31.61:9443**(自签证书,首次需点“继续前往”;见下方「为什么会一直 Connecting」) | | API / 直连 | http://localhost:9001(后台界面走这个地址会一直 Connecting,仅用于 API/调试) | | 登录账号 | `System` | | 登录密码 | `Ld@42d0ef50ac5d0efa`(也存在 `.env` 的 `LIBREDESK_SYSTEM_USER_PASSWORD`,登录后建议改掉) | ## 组成 | 服务 | 镜像 | 容器名 | 宿主端口 | | --- | --- | --- | --- | | app | libredesk/libredesk:**v2.9.1**(当前稳定版) | libredesk_app | **127.0.0.1**:9001 → 9000(仅本机/隧道) | | db | pgvector/pgvector:pg18(本机已缓存;官方文档默认 postgres:17-alpine,本机拉取该镜像一直失败,见下方「已知偏差」) | libredesk_db | 127.0.0.1:5433 → 5432 | | redis | redis:7-alpine | libredesk_redis | 127.0.0.1:6380 → 6379 | | tls | nginx:alpine | libredesk_tls | 9443 → 443 | | bridge-tools | 本仓库 `./bridge-tools`(Node 24,零依赖) | libredesk_bridge_tools | 127.0.0.1:4101 → 4100(LibreDesk 内部走 `bridge-tools:4100`) | 数据:`postgres-data`、`redis-data` 两个 Docker 卷;上传文件在 `./uploads`。 配置:`config.toml`(含加密密钥与 DB 密码,不入库)、`.env`(含容器密码,不入库)。 ## 为什么会一直 “Connecting...” 现象:用 `http://192.168.31.61:9001` 打开后台,右上角一直显示 `Connecting...`,app 日志反复报: ``` error upgrading tcp connection ... error="websocket: request origin not allowed by FastHTTPUpgrader.CheckOrigin" ``` 原因:libredesk v2.9.x 的 Agent 实时通道(`/ws`)在 `cmd/websocket.go` 里做了 Origin 校验, **只接受 `https` 或 `localhost` 的 Origin**,`http://<局域网IP>:9001` 一定被 403 拒绝,前端就无限重连。 解决:compose 里加了 `tls`(nginx)容器做 HTTPS 终结,后台走 **https://192.168.31.61:9443**。 证书是自签的(SAN 含 `192.168.31.61`、`127.0.0.1`、`localhost`),首次访问浏览器会告警,点“高级 → 继续前往”即可; 想彻底不告警,把 [tls/cert.pem](tls/cert.pem) 导入你电脑的“受信任的根证书颁发机构”。 另一个等效办法(不动证书):`ssh -L 9001:127.0.0.1:9001 dev@192.168.31.61`,然后开 `http://localhost:9001` (Origin 是 localhost,校验放行)。 ## 常用操作 ```bash cd /home/dev/code/yehwang-ai/libredesk docker compose ps # 状态 docker compose logs -f app # 日志 docker compose restart app # 重启 docker compose down # 停止(保留数据) docker compose down -v # 停止并删除数据卷(会丢数据) # 重设 System 用户密码(交互式) docker exec -it libredesk_app ./libredesk --set-system-user-password --config /libredesk/config.toml # 升级/切换版本:改 .env 的 LIBREDESK_IMAGE 后 recreate,启动命令会自动跑 --upgrade docker compose pull && docker compose up -d ``` ## 版本与升级 当前版本:**v2.9.1**(2026-10-28 发布的稳定版,替代 v2.9.0)。 版本演进:`v2.9.0`(初装)→ `v2.9.1-rc.1`(2026-10-28 15:06)→ `v2.9.1` 正式版(2026-10-28 15:42)。 每一次升级都只改 `.env` 的 `LIBREDESK_IMAGE` + `docker compose up -d app`,启动命令自动执行 `--install --idempotent-install` 与 `--upgrade`。 | 升级 | 迁移 | 说明 | | --- | --- | --- | | v2.9.0 → v2.9.1-rc.1 | 无(`no upgrades to run`) | 48 commits / 14 PR,config.sample.toml 逐字节一致 | | v2.9.1-rc.1 → v2.9.1 | 无(`no upgrades to run`) | 仅 2 commits / 1 个前端文件(automation 帮助文案对齐),无 schema 变化 | 升级前的备份(都在 [backups/](backups)): | 时间 | DB 备份 | 当时版本 | | --- | --- | --- | | 2026-10-28 15:02 | [libredesk-v2.9.0-20261028-1502.dump](backups/libredesk-v2.9.0-20261028-1502.dump)(633 TOC 条目) | v2.9.0 | | 2026-10-28 15:40 | [libredesk-v2.9.1-rc.1-20261028-1540.dump](backups/libredesk-v2.9.1-rc.1-20261028-1540.dump) | v2.9.1-rc.1 | **回滚**(到目前为止从没跑过迁移,回滚只是切镜像,不动数据):把 `.env` 的 `LIBREDESK_IMAGE` 改成目标版本(如 `libredesk/libredesk:v2.9.0`)再 `docker compose up -d app`。 只有当某次升级真的执行了迁移时才需要恢复 dump: ```bash docker compose stop app docker compose exec -T db psql -U libredesk -d libredesk -c 'drop schema public cascade; create schema public;' docker compose exec -T db pg_restore -U libredesk -d libredesk --no-owner < backups/<对应版本>.dump docker compose up -d app ``` v2.9.1 的主要变化:邮件主题/发件人 MIME 解码、IMAP 启动即扫描、`/health` 数据库不可用时返回非 200(已用于 compose 的 app healthcheck)、10 月安全审计的 5 个修复([PR #733](https://github.com/abhinavxd/libredesk/pull/733))、依赖漏洞升级([PR #742](https://github.com/abhinavxd/libredesk/pull/742))、AI 回复期间新消息继续接答、自动分配跳过 away 的 agent、日期筛选月份跳转、自定义属性可点击、automation 模板变量帮助等。详见 [release notes](https://github.com/abhinavxd/libredesk/releases/tag/v2.9.1)。 ## 当前业务配置(2026-10-28) | 项 | 状态 | | --- | --- | | AI completion | `qwen-max` @ DashScope(openai 兼容),temperature 0.3、max_tokens 800 | | AI embedding | `text-embedding-v4`,1024 维;108 篇帮助文章已嵌入(启动日志 `loaded embeddings into memory count=108`) | | 通知邮件 / OTP | 163 SMTP(smtp.163.com:465, TLS),发件人 `Yehwang Support ` | | 团队 | 「Wholesale Support」,Europe/Berlin,Round robin | | 帮助中心 | `yehwang-help`(已启用,9 个分类 / 108 篇文章,已挂 livechat inbox 1) | | AI Assistant | 「Yehwang Assistant」,friendly/balanced,max_turns 8,handoff + 引用开启,fallback team = Wholesale Support | | AI Tools | `search_products` / `search_orders` / `search_inventory` / `get_customer_info`(后两个 requires_verification) | | 渠道 inbox | **Website(livechat)** 已建:id=1,uuid `81b679b0-33fb-4796-9f83-dcc0f43231cc`;email / WhatsApp 待做 | | 自动化 | 规则「Assign new conversations to AI Assistant」:新会话 → 分配给 Yehwang Assistant | | 站点名 | `Yehwang Support` | > 换 AI 模型时注意:`qwen-plus-latest` 在这套长 prompt 下不调用工具(会凭自身知识乱答并编造引用),已验证 `qwen-max` 正常。 ## Live Chat 接入(widget) ```html ``` 匿名访客即可发起会话;已登录客户可用站点后端签 JWT(`POST /api/v1/widget/chat/auth/exchange`)做身份锚定。 ## 运维:备份 / 访问控制 / 安全头 **备份(已定时)** - 脚本:[scripts/backup.sh](scripts/backup.sh),产物在 [backups/](backups):`db-.dump`(pg_dump -Fc)、`uploads-.tar.gz`、`config.toml.`、`env.`; - 校验:每个 dump 会用 `pg_restore -l` 读出 TOC(当前 629 条),失败则脚本非 0 退出; - 保留 **14 天**(`find -mtime +14 -delete`); - cron(dev 用户,已安装):`0 3 * * * cd .../libredesk && ./scripts/backup.sh >> logs/backup.log 2>&1`; - 恢复演练(已验证过一次:57 张表 / 108 篇文章): ```bash docker cp backups/db-.dump libredesk_db:/tmp/restore.dump docker compose exec -T db createdb -U libredesk libredesk_restore_test docker compose exec -T db pg_restore -U libredesk -d libredesk_restore_test --no-owner /tmp/restore.dump docker compose exec -T db psql -U libredesk -d libredesk_restore_test -tAc "select count(*) from help_articles" docker compose exec -T db dropdb -U libredesk libredesk_restore_test ``` **访问控制** - `9001`(明文 app)只绑 `127.0.0.1`,局域网只能走 `https://192.168.31.61:9443`;本机/SSH 隧道调试不受影响; - nginx 已加 `TLSv1.2/1.3`、`X-Content-Type-Options: nosniff`、`Referrer-Policy`(X-Frame-Options 由应用自己发,避免重复)。 ### ⚠️ bridge-tools 依赖本机 DB 隧道 bridge-tools 的 4 个工具都要访问 yehwang 业务 RPC(`host.docker.internal:9632/9612/9509/9602`), 而这些服务依赖本机到 QA1 的 SSH 隧道(`172.18.0.1:3318` MySQL 等)。**隧道没起时**: - `search_products`:`/product/list` 报 Internal Server Error → 工具回退 autocomplete,**只有商品名、没有价格/库存**; - `search_orders` / `get_customer_info`:RPC 返回 `SQLSTATE[HY000] [2002] Connection refused`。 启动顺序:先 `yw-db-tunnel start`(`yw-db-tunnel status` 确认“已转发”),再 `docker compose up -d`。 隧道断线后工具会“半残”,排查时先看 `docker compose logs bridge-tools` 与 `testdb "select 1"`。 **隧道已配置自启 / 自愈**(dev 用户 crontab): ``` @reboot sleep 60; /home/dev/code/yehwang-ai/libredesk/scripts/ensure-tunnel.sh */5 * * * * /home/dev/code/yehwang-ai/libredesk/scripts/ensure-tunnel.sh ``` - [scripts/ensure-tunnel.sh](scripts/ensure-tunnel.sh) 幂等:隧道完整时静默退出,异常时 `yw-db-tunnel start` 并写 `logs/tunnel.log`; - 依赖 cron 开机自启(已确认 enabled)和 `yw-devbox` 容器(restart=unless-stopped,已确认); - 如需手动确认:`yw-db-tunnel status` + `testdb "select 1"`。 ## 已知偏差(相对官方 quickstart) - **DB 镜像**:官方 compose 用 `postgres:17-alpine`,本机从 docker.io / 各镜像源拉取该 tag 均失败(docker.io 长时间无进展、1panel 403、imgdb 层校验失败), 因此改用本机已缓存的 `pgvector/pgvector:pg18`(官方 `postgres` 镜像的 PG18 基础映像,`crm-new` 项目的 LibreDesk 已在用,兼容)。 PG18 的数据目录是 `/var/lib/postgresql`,compose 已按此挂载;如以后想换回 `postgres:17-alpine`,**不能直接复用数据卷**(18→17 需 dump/restore)。 - **System 用户密码强度**:libredesk 要求 10-72 位且含大小写+数字+特殊字符,纯随机 hex 会被拒绝(启动日志 `system user password is not strong`)。 ## 注意事项 - `app.encryption_key` 首次启动后**不要改**,否则已保存的密钥(如收件箱密码)无法解密。 - `config.toml` 里 `disable_secure_cookies = true` 是给 http://localhost:9001 直连用的;如果只走 https,可以改回 `false` 更安全。 - 反代已按官方要求设置 `X-Client-IP $remote_addr`(限流/审计需要),见 [tls/nginx.conf](tls/nginx.conf)。 - 初始化时 compose 的 command 会执行 `--install --idempotent-install`,这是幂等的;**不要**对已有数据库手工跑 `--install`(官方文档警告它会删除已有数据)。 - 如需公网/域名访问,建议按官方文档加 Nginx 反向代理,并在 Cloudflare 场景下转发 `CF-Connecting-IP`。