Files
crm-ai/docs/deploy-wangliang.md
T

172 lines
9.4 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.
# crm-ai 在 wangliang 工作区的部署记录
> 部署时间:2026-10-23 | 部署位置:`/data/dev/wangliang/crm-ai` | 代码版本:`main @ 1ae25f1`
>
> 本文件记录这套栈**实际跑成什么样**、和仓库默认配置差在哪、怎么运维、以及还缺哪些凭据。
> 环境相关的临时信息写在这里,通用约定见 `/data/dev/_shared/NOTES.md`。
## 1. 交付摘要
一套自包含的客服 + CRM 栈(与仓库 `docker-compose.yml` 一致,Compose 项目名 `crm-new`):
| 组件 | 容器 | 宿主端口 | 状态 |
|---|---|---|---|
| LibreDesk v2.9.0-rc.10(客服工作台 + 内置 AI) | `crmnew-libredesk` | `9000` | ✅ healthy |
| Twenty CRM v2.30.1(server) | `crmnew-twenty-server` | `3100` | ✅ healthy |
| Twenty worker | `crmnew-twenty-worker` | — | ✅ running |
| bridge(业务工具 / RPC 集成) | `crmnew-bridge` | `4100` | ✅ healthy |
| PostgreSQL 18 + pgvector | `crmnew-postgres` | `127.0.0.1:5440` | ✅ healthy |
| Redis 8.8 | `crmnew-redis` | `127.0.0.1:6390` | ✅ healthy |
| IMAP ID 注入代理(163 专用) | `crmnew-imap-proxy` | `127.0.0.1:1993` | ✅ running |
数据卷:`crm-new_pg-data`、`crm-new_redis-data`、`crm-new_twenty-data`(`docker compose down` 不会删)。
## 2. 访问地址与账号
| 入口 | 地址 | 账号 |
|---|---|---|
| LibreDesk(工作台 / 帮助中心 / widget) | https://wangliang-crm.dev.gaia888.com | `System` /密码见下方命令 |
| Twenty CRM | https://wangliang-twenty.dev.gaia888.com | `admin@yehwang.com` /密码见下方命令 |
| bridge(调试/集成) | https://wangliang-crmbridge.dev.gaia888.com | 请求头 `X-Tools-Key`,值见下方命令 |
```bash
cd /data/dev/wangliang/crm-ai
grep '^LIBREDESK_SYSTEM_USER_PASSWORD=' .env # LibreDesk System 密码
grep '^TWENTY_ADMIN_PASSWORD=' .env # Twenty 管理员密码
grep '^TOOLS_SHARED_KEY=' .env # bridge 工具密钥
```
> 密钥只存在 `.env`(600)与 `libredesk/config/config.toml`(600),两者都已被 `.gitignore` 排除,**不要提交**。
## 3. 与仓库默认配置的差异(重要)
| 项 | 仓库默认 | 本环境 | 原因 |
|---|---|---|---|
| `LIBREDESK_IMAGE` | `libredesk/libredesk:v2.9.0-rc.10` | `libredesk/libredesk:v2.9.0-rc.10-**arm64**` | 宿主是 ARM64,`v2.9.0-rc.10` 只有 amd64;官方另发了 `-arm64` 同版本 tag,实测原生 `linux/arm64` 运行 |
| `LIBREDESK_BASE_URL` | `http://localhost:9000` | `https://wangliang-crm.dev.gaia888.com` | 走宿主 nginx 的 HTTPS |
| `TWENTY_SERVER_URL` | `http://192.168.31.61:3100` | `https://wangliang-twenty.dev.gaia888.com` | 前端 `REACT_APP_SERVER_BASE_URL` 用的就是它(已核对页面内联配置) |
| `RECOMMEND_URL` | 测试服地址 | `jsonrpc://host.docker.internal:24503` | 用 **本工作区** 的 product-service(宿主 socat 24503 → 容器 9503) |
| `ORDER_API_URL` | 测试服地址 | `jsonrpc://host.docker.internal:24505` | trading-service(24505 → 9505) |
| `INVENTORY_API_URL` | 测试服地址 | `jsonrpc://host.docker.internal:24509` | eta-service(24509 → 9509) |
| `MEMBER_RPC_URL` | 测试服地址 | `jsonrpc://host.docker.internal:24506` | member-service(24506 → 9506) |
| `IDENTITY_DEV_MODE` | `false` | `true` | dev 环境方便 widget 联调;**上生产前改回 `false`** |
| `public-gateway` / `cloudflared` | compose 里默认启动 | **未启动** | 已有宿主 nginx 直出 HTTPS,不需要 Cloudflare 临时隧道 |
`host.docker.internal` 由 compose 的 `extra_hosts` 注入,指向宿主;`24503-24509` 是本工作区的 RPC 宿主转发端口
(见 `conf/dev/rpc-forward.sh`,cron 每分钟自愈)。
## 4. 已完成初始化
### LibreDesk
- `System` 账号可登录(浏览器实测落到 `/inboxes/assigned`)。
- `app.root_url = https://wangliang-crm.dev.gaia888.com`(`scripts/set-public-url.js`)。
- 10 个 bridge 工具已注册(`scripts/register-tools.js`):`search_products / search_orders / search_inventory /
search_kb / search_email_history / collect_info / send_verification_code / verify_email_code / handoff_to_human /
create_opportunity`。
- 默认助理 `Yehwang Assistant`(#1,10 个工具、引用与 handoff 开启)。
- Live chat Inbox `Website`(#1,uuid `ad25d7a4-722d-4561-aebf-9d8f60952d09`)。
- Automation:新会话自动分配给助理(#1,enabled)。
### Twenty
- Workspace `Yehwang`:`2ff5a56b-95d8-40e1-85cf-529ad3a70ed7`(`ACTIVE`)。
- API key 已生成并写入 `.env` 的 `TWENTY_API_KEY`;GraphQL `companies` 查询验证通过。
- 浏览器实测可登录,首次进入 `/install-apps`(Twenty 的新工作区引导页,正常现象)。
### bridge
- `/healthz` 正常,10 个工具就绪。
- 实测 `search_products` 直接命中**本工作区真实商品数据**(如 `Stainless Steel Y-Chain Necklace` / `$6.73` /
`product_id=11079`),说明 `host.docker.internal:24503` 的 JSONRPC 链路是通的。
- `search_orders` 未验证身份时按设计返回 `verification_required`。
## 5. 运维命令
```bash
cd /data/dev/wangliang/crm-ai
docker compose ps # 状态
docker compose logs -f --tail=100 libredesk
docker compose logs -f --tail=100 twenty-server
docker compose logs -f --tail=100 bridge
docker compose start # 启动已有容器
docker compose stop # 停止(保留数据)
docker compose restart libredesk # 重启单个服务
# 改 .env 后(bridge 必做;libredesk 也要重建才会读到新 env)
docker compose up -d --force-recreate bridge
docker compose up -d --force-recreate libredesk
# 改 LibreDesk 配置模板后
node scripts/render-config.js && docker compose up -d --force-recreate libredesk
# 备份(DB + Twenty 自带数据都在 PG 里;卷里是上传文件)
mkdir -p backups
docker exec crmnew-postgres pg_dump -U crmnew -Fc libredesk > backups/libredesk-$(date +%F).dump
docker exec crmnew-postgres pg_dump -U crmnew -Fc twenty > backups/twenty-$(date +%F).dump
docker exec crmnew-postgres pg_dump -U crmnew -Fc bridge > backups/bridge-$(date +%F).dump
# 恢复
docker exec -i crmnew-postgres pg_restore -U crmnew -d libredesk --clean --if-exists < backups/libredesk-YYYY-MM-DD.dump
```
所有容器都是 `restart: unless-stopped`,Docker 守护进程重启后会自己拉起来。
## 6. 域名反向代理
宿主 nginx 新增了**独立**配置文件 `/etc/nginx/conf.d/zz-wangliang-crm.conf`:
- `wangliang-crm.dev.gaia888.com` → `127.0.0.1:9000`
- `wangliang-twenty.dev.gaia888.com` → `127.0.0.1:3100`
- `wangliang-crmbridge.dev.gaia888.com` → `127.0.0.1:4100`
- 80 → 308 跳 HTTPS;证书复用 `*.dev.gaia888.com`(通配一级域名,三个域名都被覆盖)。
它**没有改** `devstack.conf` 的 map/正则,因此不影响其它工作区。
改完后的自检 / 重载(query 用户没有 root,用容器代跑):
```bash
docker run --rm --privileged --pid=host redis:7-alpine \
sh -c 'nsenter -t 1 -m -u -i -n -p /usr/sbin/nginx -t'
docker run --rm --privileged --pid=host redis:7-alpine \
sh -c 'nsenter -t 1 -m -u -i -n -p /usr/sbin/nginx -s reload'
```
回滚(只需删掉这个文件并 reload,其它站点不受影响):
```bash
docker run --rm -v /etc/nginx/conf.d:/c redis:7-alpine rm -f /c/zz-wangliang-crm.conf
# 再执行上面的 nginx -t / -s reload
```
## 7. 尚未配置(需要真实凭据,不是代码问题)
| 项 | 现状 | 补法 |
|---|---|---|
| **AI Provider(DashScope)** | `LLM_*` / `EMB_*` 为空,助理不会真正调模型 | `DASHSCOPE_API_KEY=sk-xxx node scripts/configure-ai.js`(需能访问 dashscope) |
| **SMTP / 163 邮件** | `SMTP_*` 为空,OTP 与邮件渠道不可用 | 填 `.env` 后 `node scripts/configure-email.js` + `node scripts/add-email-inbox.js` |
| **知识库 RAG(search_kb)** | 无 `RAG_PG_URL`,工具返回 503 | 指向旧 KB 库后运行 `scripts/import-kb-helpcenter.js` / `rebuild-kb-index.sh` |
| **WhatsApp 渠道** | 无 Meta 凭据 | 填 `WA_*` 后 `scripts/add-whatsapp-inbox.js`;需要公网回调(本栈已有 HTTPS,可不用 cloudflared) |
| **public-gateway / cloudflared** | 未启动 | 需要 Cloudflare 临时隧道时再 `docker compose up -d public-gateway cloudflared` |
> `IDENTITY_DEV_MODE=true` 只适合 dev;上生产前改回 `false`。
## 8. 验证记录(2026-10-23)
```text
$ curl -o /dev/null -w '%{http_code}' https://wangliang-crm.dev.gaia888.com/health # 200
$ curl -o /dev/null -w '%{http_code}' https://wangliang-twenty.dev.gaia888.com/healthz # 200
$ curl -o /dev/null -w '%{http_code}' https://wangliang-crmbridge.dev.gaia888.com/healthz # 200
$ curl -s https://wangliang-crmbridge.dev.gaia888.com/healthz
{"ok":true,"service":"crm-tools","tools":[10 个],"sites":["www","us","eu"]}
$ curl -s -X POST http://127.0.0.1:4100/tools/search_products -H 'X-Tools-Key: …' -d '{"query":"stainless steel necklace"}'
{"ok":true,"products":[{"name":"Stainless Steel Y-Chain Necklace","price":"$6.73","product_id":11079}]}
```
浏览器(Playwright 真 Chrome,1440×900):
- LibreDesk 登录成功 → `/inboxes/assigned`(截图 `docs/screenshots/wangliang-libredesk-inbox.png`)
- Twenty 登录成功 → `/install-apps` 引导页(截图 `docs/screenshots/wangliang-twenty-onboarding.png`)
- 回归:`wangliang-www` 仍 200,`wangliang-agent` 仍 302(宿主 nginx 未被改坏)
资源占用:约 1.9 GB 内存(Twenty worker 约 1.0 GB + server 0.6 GB + PG/Redis/bridge/LibreDesk 约 0.3 GB)。