From a161a0eee9786e47c2086fb353e22a3c7b54e5c0 Mon Sep 17 00:00:00 2001 From: wangliang Date: Fri, 23 Oct 2026 10:45:30 +0800 Subject: [PATCH] docs: clarify RPC/Cloudflare tunnels are local-only --- README.md | 16 ++++-- docs/environments.md | 124 ++++++++++++++++++++++++++++++++++++++++ docs/go-live.md | 41 +++++++++---- docs/runbook.md | 10 ++-- scripts/public-https.sh | 3 +- scripts/rpc-tunnel.sh | 3 +- scripts/serve-web.sh | 2 +- 7 files changed, 175 insertions(+), 24 deletions(-) create mode 100644 docs/environments.md diff --git a/README.md b/README.md index 9470e1d..715ae50 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ | Twenty Workspace | ✅ 已创建(admin@yehwang.com,workspace 已 ACTIVE) | | Twenty API Key | ✅ 已在库内生成并写入 `.env`,GraphQL 验证通过 | | 商机写入 | ✅ `create_opportunity` 实测创建 company/person/opportunity/note/task | -| 业务 RPC | ✅ 测试服 24503/24505/24506/24509 外网被封,已用 SSH 隧道(`scripts/rpc-tunnel.sh`) | +| 业务 RPC | ✅ 本地开发用 SSH 隧道(`scripts/rpc-tunnel.sh`);测试/生产应直连内网 RPC,不需要隧道 | | 邮件通知(OTP) | ✅ 163 SMTP 已配置,实测验证码邮件已送达 163 收件箱 | | Email 渠道 | ✅ 163 收件(imap-proxy 绕过 Unsafe Login)+ AI 回复邮件(模板)已实测 | | IMAP 代理 | ✅ `services/imap-id-proxy`(LibreDesk 不发 IMAP ID,163 会拒绝 SELECT) | @@ -80,15 +80,17 @@ crm-new/ │ ├── configure-email.js # 配置 163 SMTP(通知/OTP 邮件) │ ├── add-email-inbox.js # 配置 Email Inbox + 默认外发模板 + Automation │ ├── e2e-widget-jwt.js # 端到端验证 widget JWT + 订单工具 -│ ├── rpc-tunnel.sh # 测试服 JSON-RPC 端口 SSH 隧道(bridge 依赖) -│ ├── public-https.sh # Cloudflare Tunnel 公网 HTTPS + 白名单网关 +│ ├── rpc-tunnel.sh # 仅本地开发:测试服 RPC 端口 SSH 隧道 +│ ├── public-https.sh # 仅本地联调:Cloudflare Quick Tunnel + 白名单网关 │ ├── set-public-url.js # 更新 LibreDesk app.root_url │ ├── import-kb-helpcenter.js # 旧 KB -> 帮助中心文章(幂等) │ ├── verify-rag.js # 临时助手 + preview,验证检索/引用 -│ └── smoke.sh +│ ├── smoke.sh +│ └── serve-web.sh # 仅本地预览 demo 页面 ├── web/ # 站点接入:ai-snippet.js + demo.html(widget JWT 演示) -├── docs/ # 架构、LibreDesk 配置、接口对照、迁移说明、运维手册 +├── docs/ # 架构、LibreDesk 配置、环境差异、上线/运维手册 │ ├── go-live.md # 上线文档(范围/切流/验收/监控/回滚) +│ ├── environments.md # 本地开发 vs 测试/生产:RPC/Cloudflare 隧道差异 │ ├── human-routing.md # Email/WhatsApp 人工团队分配 │ └── plan-a.md # 方案 A:bridge 接管 AI 编排进度 └── deploy/nginx.conf.example @@ -107,6 +109,8 @@ bash scripts/bootstrap.sh bash scripts/smoke.sh ``` +> `scripts/rpc-tunnel.sh`、`scripts/public-https.sh`、`scripts/serve-web.sh` 仅本地开发/联调使用;测试/生产环境不需要,见 [docs/environments.md](docs/environments.md)。 + 启动完成后: 1. **LibreDesk**(`System`,密码见 `.env` 的 `LIBREDESK_SYSTEM_USER_PASSWORD`) @@ -184,6 +188,8 @@ bash scripts/serve-web.sh # http://localhost:8088/demo.html ## 运维 +环境差异见 [docs/environments.md](docs/environments.md)(RPC 隧道/Cloudflare 隧道仅本地开发用)。 + 上线清单见 [docs/go-live.md](docs/go-live.md),常用命令见 [docs/runbook.md](docs/runbook.md)(启动/停止/日志/备份/升级/回滚/排错)。 ## 测试 diff --git a/docs/environments.md b/docs/environments.md new file mode 100644 index 0000000..cc578d2 --- /dev/null +++ b/docs/environments.md @@ -0,0 +1,124 @@ +# 环境差异:本地开发 / 测试 / 生产 + +> 结论:`rpc-tunnel.sh` 和 `public-https.sh` 是**本地开发联调工具**,测试/生产环境不应依赖它们。 + +## 1. 对比表 + +| 能力 | 本地开发(当前机器) | 测试 / 生产 | +|---|---|---| +| 业务 RPC | 用 SSH 隧道 `scripts/rpc-tunnel.sh`,因为 RPC 端口外网不可达 | **不需要隧道**,直接填内网 RPC 地址(服务 DNS / VPC / 专线) | +| RPC 地址 | `jsonrpc://:24503` 等隧道网关地址 | `jsonrpc://:24503` 等真实内网地址 | +| 公网 HTTPS | Cloudflare Quick Tunnel + `scripts/public-https.sh` | **不需要 Quick Tunnel**,用正式域名 + Ingress/Nginx/ALB + TLS | +| WhatsApp webhook | 临时 Quick Tunnel URL,重启会变 | 正式域名,例如 `https://crm.example.com/webhooks/whatsapp/...` | +| 公网路径白名单 | `public-gateway`(本地 compose 服务) | 由 Ingress/Nginx 统一处理,或保留 gateway 作为内部服务 | +| Demo 页面 | `scripts/serve-web.sh`,:8088 | 不需要 | +| 数据库/Redis | compose 内 Postgres/Redis,宿主机端口仅绑 `127.0.0.1` | 使用托管数据库/Redis 或内网集群,不暴露宿主机端口 | +| 环境变量 | `.env` 指向本地/测试地址 | `.env` 指向测试/生产真实地址 | +| 密钥 | 本地 `.env` | Secret Manager / CI/CD Secret,不入库 | + +## 2. RPC:本地隧道 vs 测试/生产直连 + +### 本地开发 + +RPC 端口外网不可达时,才需要: + +```bash +bash scripts/rpc-tunnel.sh --apply +``` + +它会: + +- 在本机建 SSH 隧道到远端 RPC +- 把 `.env` 的 RPC URL 改为隧道网关地址 +- 重建 bridge + +### 测试 / 生产 + +**不要运行 `rpc-tunnel.sh`。** + +直接配置: + +```env +RECOMMEND_URL=jsonrpc://:24503 +ORDER_API_URL=jsonrpc://:24505 +MEMBER_RPC_URL=jsonrpc://:24506 +INVENTORY_API_URL=jsonrpc://:24509 +``` + +要求: + +- bridge 容器能直接访问这些地址 +- 测试/生产网络放行对应端口 +- 不要指向开发机的 SSH 隧道网关 + +如果测试/生产网络确实隔离,应该用 **VPC 对等连接 / 专线 / VPN / 内网反向代理**,而不是开发机上的 SSH 隧道。 + +## 3. 公网 HTTPS:Quick Tunnel vs 正式域名 + +### 本地开发 + +只有本地联调 WhatsApp/公网 webhook 时才需要: + +```bash +bash scripts/public-https.sh +``` + +特点: + +- Cloudflare Quick Tunnel +- URL 每次重启可能变化 +- 需要重新更新 LibreDesk `root_url` 和 Meta webhook +- 只适合临时联调 + +### 测试 / 生产 + +**不要使用 Cloudflare Quick Tunnel。** + +使用: + +- 正式域名(`crm.example.com`) +- Ingress / Nginx / ALB / API Gateway +- 正式 TLS 证书 +- 固定公网出口 + +配置: + +```env +PUBLIC_BASE_URL=https://crm.example.com +``` + +并同步: + +- LibreDesk `app.root_url` +- Meta WhatsApp callback URL +- `public-gateway` 的上游地址(如果保留) + +### public-gateway 的去留 + +`services/public-gateway` 只负责路径白名单: + +``` +/webhooks/whatsapp/ +/hc/ +/widget* +/static/public/ +``` + +测试/生产可以: + +- 继续保留它,放在 Ingress 后面 +- 或者把同样的路径规则直接写进 Ingress/Nginx + +Quick Tunnel 只是本地把请求转发进来的手段,不是生产架构的一部分。 + +## 4. 测试/生产上线检查 + +- [ ] 未运行 `rpc-tunnel.sh` +- [ ] RPC URL 指向内网真实地址,不是 `172.23.0.1` +- [ ] 未运行 `public-https.sh` +- [ ] `PUBLIC_BASE_URL` 是正式 HTTPS 域名 +- [ ] LibreDesk `root_url` 是正式域名 +- [ ] Meta webhook 是正式域名 +- [ ] 数据库/Redis 不暴露公网 +- [ ] 不使用 `serve-web.sh` 的 8088 demo +- [ ] 密钥来自 Secret Manager / CI Secret,不在仓库和镜像里 diff --git a/docs/go-live.md b/docs/go-live.md index 4b7186e..1cf29f3 100644 --- a/docs/go-live.md +++ b/docs/go-live.md @@ -53,6 +53,17 @@ Email (inbox 2) / WhatsApp (inbox 3) --- +## 2.1 环境差异(本地开发 vs 测试/生产) + +> 详见 [environments.md](environments.md)。 + +- `scripts/rpc-tunnel.sh`:**仅本地开发**,因为 RPC 端口外网不可达 +- `scripts/public-https.sh`:**仅本地联调**,Cloudflare Quick Tunnel +- 测试/生产:RPC 直接配内网地址,公网 HTTPS 用正式域名 + Ingress/Nginx/ALB +- 测试/生产不应运行上述两个脚本 + +--- + ## 3. 访问入口 | 服务 | 地址 | 备注 | @@ -97,13 +108,13 @@ Email (inbox 2) / WhatsApp (inbox 3) - [ ] `.env` 已备份,且权限为 `600` - [ ] `docker compose config -q` 通过 -- [ ] RPC 隧道可用(商品/订单/库存) +- [ ] 本地开发:RPC 隧道可用;测试/生产:RPC 内网地址可直达 - [ ] LibreDesk webhook `Bridge AI` 为启用状态 - [ ] LibreDesk 规则 1 关闭 - [ ] 规则 4/5 指向 `Wholesale Support` - [ ] agent1/agent2 可登录,必要时设为在线 - [ ] WhatsApp access token 未过期(当前 token 有到期时间) -- [ ] 公网 URL 与 Meta webhook 已同步 +- [ ] 本地开发:Quick Tunnel 与 Meta webhook 已同步;测试/生产:正式域名与 Meta webhook 已同步 - [ ] 163 SMTP / IMAP 可用 - [ ] 已做数据库备份 - [ ] bridge 测试通过 @@ -162,9 +173,11 @@ bash scripts/rebuild-kb-index.sh node scripts/upgrade-kb-schema.js ``` -### 6.4 RPC 隧道 +### 6.4 RPC 隧道(仅本地开发) -商品/订单/库存依赖本机到内网的 RPC 隧道: +> 测试/生产不需要这一步;直接配置内网 RPC 地址即可。 + +本地 RPC 端口外网不可达时才需要: ```bash bash scripts/rpc-tunnel.sh @@ -172,7 +185,11 @@ bash scripts/rpc-tunnel.sh 隧道断了会导致 `search_products/search_orders/search_inventory` 失败。 -### 6.5 公网 HTTPS / WhatsApp webhook +### 6.5 公网 HTTPS / WhatsApp webhook(仅本地联调) + +> 测试/生产不要用 Cloudflare Quick Tunnel;使用正式域名 + Ingress/Nginx/ALB + TLS。 + +本地联调: ```bash bash scripts/public-https.sh @@ -308,10 +325,10 @@ bridge 关键日志: ### 外部依赖巡检 -- RPC 隧道进程 +- 本地开发:RPC 隧道进程 +- 本地开发:Cloudflare tunnel 状态 +- 测试/生产:内网 RPC 可达性、Ingress/证书、WhatsApp token 剩余有效期 - 163 SMTP/IMAP -- WhatsApp token 剩余有效期 -- Cloudflare tunnel 状态 - 未分配/团队队列积压 --- @@ -386,8 +403,8 @@ docker compose stop bridge ### 高 1. **单点**:bridge 只有一个实例;bridge 挂了 Live chat 无 AI 回复。 -2. **RPC 隧道**:依赖本机 SSH 隧道,断了商品/订单/库存工具不可用。 -3. **公网 URL**:Cloudflare Quick Tunnel URL 不固定,重启可能失效。 +2. **RPC 隧道(仅本地开发)**:依赖本机 SSH 隧道,断了商品/订单/库存工具不可用。测试/生产应直连内网 RPC。 +3. **公网 URL(仅本地开发)**:Cloudflare Quick Tunnel URL 不固定,重启可能失效。测试/生产使用正式域名。 4. **WhatsApp token**:临时 token 有到期时间,需要提前续期。 5. **Email 历史数据为空**:`kb_mail_docs` 只有测试邮件,真实客户历史未 ingest。 @@ -453,8 +470,8 @@ TWENTY_BASE_URL / TWENTY_API_KEY ``` scripts/bootstrap.sh -scripts/rpc-tunnel.sh -scripts/public-https.sh +scripts/rpc-tunnel.sh # 仅本地开发 +scripts/public-https.sh # 仅本地联调 scripts/build-site-map.js scripts/rebuild-kb-index.sh scripts/e2e-widget-jwt.js diff --git a/docs/runbook.md b/docs/runbook.md index 3e057b6..ab39b7b 100644 --- a/docs/runbook.md +++ b/docs/runbook.md @@ -77,10 +77,12 @@ node scripts/eval-offline.js # 真实模型离线评测(fake LibreDesk,不写真实会话;会调 LLM/RPC) node scripts/eval-live.js -# 公网 HTTPS(WhatsApp webhook 需要):Cloudflare Quick Tunnel + 路径白名单网关 +# 公网 HTTPS(仅本地联调需要):Cloudflare Quick Tunnel + 路径白名单网关 +# 测试/生产:不要跑这个脚本,使用正式域名 + Ingress/Nginx + TLS bash scripts/public-https.sh -# 测试服 RPC 端口外网被封:建 SSH 隧道并让 bridge 指向隧道(网关 IP) +# 仅本地开发:测试服 RPC 端口外网被封时建 SSH 隧道 +# 测试/生产:不要跑这个脚本,直接把 RPC URL 配成内网可达地址 bash scripts/rpc-tunnel.sh --apply # 配置 163 SMTP(自动重启 LibreDesk) @@ -168,6 +170,6 @@ ss -ltnp | grep -E ':(9000|3100|4100|5440|6390)\s' | 管理员后台实时更新不工作 | 通过 http + IP 访问时 agent websocket 拒绝非 HTTPS 来源 | POC 可忽略;生产用 HTTPS 或经 localhost 访问 | | collect_info 槽位丢失 | Redis 不可用,退回了进程内存 | 检查 `REDIS_URL=redis://redis:6379/3` 和 `docker logs crmnew-bridge` 的 lead store 告警 | | 多站点商品推荐串站 | `bridge/config/sites.json` 的 inbox 映射没配 | 把对应 inbox 数字 ID 指到 us/eu/www profile,重建 bridge | -| WhatsApp webhook 收不到 | 没有公网 HTTPS / Meta 回调地址不对 | 跑 `bash scripts/public-https.sh`,把输出的 `.../webhooks/whatsapp/` 配到 Meta;quick tunnel URL 每次重启会变 | +| WhatsApp webhook 收不到 | 没有公网 HTTPS / Meta 回调地址不对 | 本地联调跑 `bash scripts/public-https.sh`;测试/生产使用正式域名,不要用 Quick Tunnel | | 公网访问到管理后台 | 网关白名单配置 | `services/public-gateway` 只放行 `/webhooks/whatsapp/*`、`/hc/*`、`/widget*`、`/static/public/*`,其余 404 | -| AI 回复"系统暂时无法查询订单" | 测试服 24503/24505/24506/24509 外网 TCP 被封,bridge 8s 超时 | 跑 `bash scripts/rpc-tunnel.sh --apply`,bridge RPC 指向 docker 网关(隧道只绑网关,不暴露 LAN) | +| AI 回复"系统暂时无法查询订单" | RPC 不可达,bridge 8s 超时 | 本地开发跑 `bash scripts/rpc-tunnel.sh --apply`;测试/生产检查内网 RPC 地址/网络策略,不要用开发机隧道 | diff --git a/scripts/public-https.sh b/scripts/public-https.sh index cdb7883..0947cbc 100755 --- a/scripts/public-https.sh +++ b/scripts/public-https.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash -# 启动/重启公网 HTTPS(Cloudflare Quick Tunnel),并把 LibreDesk root_url 指过去。 +# 仅本地联调:启动/重启公网 HTTPS(Cloudflare Quick Tunnel),并把 LibreDesk root_url 指过去。 +# 测试/生产不要用 Quick Tunnel:使用正式域名 + Ingress/Nginx/ALB + TLS。 # 注意:quick tunnel 每次重启 URL 会变,需要重新跑本脚本(Meta 里的 webhook 也要同步改)。 set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")/.." diff --git a/scripts/rpc-tunnel.sh b/scripts/rpc-tunnel.sh index a1771e5..03df89b 100755 --- a/scripts/rpc-tunnel.sh +++ b/scripts/rpc-tunnel.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash -# 测试服 JSON-RPC 端口外网被封:在本机建 SSH 隧道,供 crm-new 的 bridge 访问。 +# 仅本地开发:测试服 JSON-RPC 端口外网被封时,在本机建 SSH 隧道。 +# 测试/生产不需要此隧道:把 RPC URL 直接配成内网可达地址。 # # 默认只启动隧道并打印 .env 需要的 4 行配置; # 加 --apply 会自动更新 .env 里的 RPC URL 并重建 bridge。 diff --git a/scripts/serve-web.sh b/scripts/serve-web.sh index ee2b957..338c067 100755 --- a/scripts/serve-web.sh +++ b/scripts/serve-web.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# 本地静态测试页(widget JWT 演示) +# 仅本地预览:静态测试页(widget JWT 演示);测试/生产不需要 set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")/../web" echo "http://localhost:${WEB_PORT:-8088}/demo.html"