Files
libredesk/README.md
T

204 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 <xx2227234215@163.com>` |
| 团队 | 「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
<script>
window.LibredeskSettings = {
baseURL: 'https://192.168.31.61:9443',
inboxID: '81b679b0-33fb-4796-9f83-dcc0f43231cc'
};
</script>
<script async src="https://192.168.31.61:9443/widget.js"></script>
```
匿名访客即可发起会话;已登录客户可用站点后端签 JWT(`POST /api/v1/widget/chat/auth/exchange`)做身份锚定。
## 运维:备份 / 访问控制 / 安全头
**备份(已定时)**
- 脚本:[scripts/backup.sh](scripts/backup.sh),产物在 [backups/](backups):`db-<ts>.dump`(pg_dump -Fc)、`uploads-<ts>.tar.gz`、`config.toml.<ts>`、`env.<ts>`;
- 校验:每个 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-<ts>.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`。