Files

439 lines
14 KiB
Markdown
Raw Permalink 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.
# 群晖 NAS + Cloudflare Tunnel + 未认证企微 部署指南
> **适用范围**:阶段一功能测试
> **目标域名**`itdesk.amanzac.com`
> **最后更新**2026-06-07
---
## 架构总览
```
HTTPS HTTP
员工手机 ──────────→ Cloudflare Edge ──────────→ cloudflared ──→ nginx:80
(企微H5) (自动SSL+CDN) Tunnel 容器 │
┌────┴────┐
│ 路由分发 │
└────┬────┘
┌──────┼──────┐
│ │ │
/itdesk/ /itagent/ /api/
H5员工端 坐席工作台 后端
```
**关键特点**
- ✅ 无需公网 IP
- ✅ 无需 SSL 证书(Cloudflare 自动处理)
- ✅ 无需开放 NAS 端口
- ✅ 未认证企微可正常使用 OAuth2 + 消息 API
---
## §1 前置条件检查清单
| # | 条件 | 你的状态 | 说明 |
|---|------|---------|------|
| 1 | 群晖 NASDS220+ 及以上) | ✅ 已确认 | 需支持 Docker(ARM 机型需确认镜像兼容) |
| 2 | Container Manager 已安装 | ✅ 已确认 | 套件中心安装 |
| 3 | Cloudflare 账号 | ✅ 已确认 | 免费版即可 |
| 4 | 域名 `amanzac.com` 已托管 Cloudflare | ✅ 已确认 | DNS 管理 → Cloudflare |
| 5 | 企微管理后台权限 | ✅ 已确认 | 需配置自建应用 |
| 6 | SSH 访问 NAS | ⬜ 待确认 | 需开启 SSH 以执行 docker compose 命令 |
---
## §2 Cloudflare Tunnel 配置
### 2.1 创建 Tunnel
1. 登录 [Cloudflare Zero Trust](https://one.dash.cloudflare.com/)
2. 左侧菜单 → **Networks****Tunnels**
3. 点击 **Create a tunnel**
4. 选择 **Cloudflared** 类型
5. 输入 Tunnel 名称,如 `itdesk-nas`
6. 点击 **Save tunnel**
### 2.2 获取 Tunnel Token
创建完成后,页面会显示安装命令,其中包含 Token:
```bash
# 示例安装命令
cloudflared service install eyJhIjoiNjM1...
# ^^^^^^^^^^^^
# 这就是 Token
```
**复制这个 Token**,后面要填到 `.env` 文件中。
### 2.3 配置 Tunnel 路由(Public Hostname
在 Tunnel 创建页面,配置 **Public Hostname**
| 字段 | 填写 | 说明 |
|------|------|------|
| Subdomain | `itdesk` | 前缀 |
| Domain | `amanzac.com` | 你的域名 |
| Type | `HTTP` | 容器内是 HTTP |
| URL | `nginx` | Docker 容器名(同一网络内) |
> ⚠️ 注意:Type 选 **HTTP**(不是 HTTPS),因为 cloudflared 和 nginx 之间走的是容器内网 HTTP。SSL 由 Cloudflare Edge 终止。
点击 **Save tunnel**
### 2.4 验证 DNS 记录
Cloudflare 会自动创建一条 CNAME 记录:
- `itdesk.amanzac.com``cfargotunnel.com`
可在 Cloudflare Dashboard → DNS → Records 中确认。
---
## §3 项目文件部署到 NAS
### 3.1 上传项目文件
**方式一:Git Clone(推荐)**
如果 NAS 上有 Git
```bash
# SSH 登录 NAS
ssh admin@NAS_IP
# 创建项目目录
mkdir -p /volume1/docker/wecom-it-desk
cd /volume1/docker/wecom-it-desk
# 克隆项目
git clone <你的仓库地址> .
```
**方式二:SCP 上传**
从开发机上传构建好的文件:
```powershell
# 在 Windows PowerShell 中执行
# 上传核心文件(不含 node_modules 和 .git
scp -r "D:\资料\03-项目开发\wecom_it_smart_desk\docker-compose.nas.yml" admin@NAS_IP:/volume1/docker/wecom-it-desk/
scp -r "D:\资料\03-项目开发\wecom_it_smart_desk\.env.nas" admin@NAS_IP:/volume1/docker/wecom-it-desk/
scp -r "D:\资料\03-项目开发\wecom_it_smart_desk\nginx" admin@NAS_IP:/volume1/docker/wecom-it-desk/
scp -r "D:\资料\03-项目开发\wecom_it_smart_desk\backend" admin@NAS_IP:/volume1/docker/wecom-it-desk/
scp -r "D:\资料\03-项目开发\wecom_it_smart_desk\frontend-h5\dist" admin@NAS_IP:/volume1/docker/wecom-it-desk/frontend-h5/dist/
scp -r "D:\资料\03-项目开发\wecom_it_smart_desk\frontend-agent\dist" admin@NAS_IP:/volume1/docker/wecom-it-desk/frontend-agent/dist/
```
**方式三:群晖 File Station**
把构建产物打包成 zip,通过 File Station 上传到 `/docker/wecom-it-desk/` 然后解压。
### 3.2 配置环境变量
```bash
cd /volume1/docker/wecom-it-desk
# 复制模板
cp .env.nas .env
# 编辑 .env 文件
vi .env
```
**必须修改的项**
```bash
# 1. 填入 Cloudflare Tunnel Token(从 §2.2 获取)
CF_TUNNEL_TOKEN=eyJhIjoiNjM1... # ← 替换为你的实际 Token
# 2. 修改数据库密码
POSTGRES_PASSWORD=YourStrongPassword123! # ← 替换为强密码
# 3. 如果 NAS 能访问公司内网 Dify,填入 Dify 配置
# 如果不能访问,留空即可(AI 功能暂不可用,不影响阶段一)
DIFY_API_URL=
DIFY_API_KEY=
```
### 3.3 构建前端(如果还没构建)
前端需要先在开发机(Windows)上构建,再上传 dist/ 目录:
```powershell
# 在 Windows 开发机上
cd "D:\资料\03-项目开发\wecom_it_smart_desk"
# 构建坐席端
cd frontend-agent
npm install
npx vite build
# 构建 H5 员工端
cd ..\frontend-h5
npm install
npx vite build
```
构建产物在 `frontend-agent/dist/``frontend-h5/dist/` 中。
---
## §4 启动服务
### 4.1 SSH 登录 NAS 启动
```bash
# SSH 登录 NAS
ssh admin@NAS_IP
# 进入项目目录
cd /volume1/docker/wecom-it-desk
# 启动所有容器(5 个容器)
docker compose -f docker-compose.nas.yml up -d
# 等待约 30 秒,检查状态
docker compose -f docker-compose.nas.yml ps
```
**预期输出**
| 容器名 | 状态 | 说明 |
|--------|------|------|
| wecom_it_cloudflared | Running | Cloudflare Tunnel |
| wecom_it_nginx | Up (healthy) | 反向代理 |
| wecom_it_backend | Up | FastAPI 后端 |
| wecom_it_postgres | Up (healthy) | PostgreSQL |
| wecom_it_redis | Up (healthy) | Redis |
### 4.2 验证服务
```bash
# 1. 内网验证(在 NAS 上执行)
curl http://localhost:18080/api/health
# 预期输出: {"status":"ok","service":"wecom-it-smart-desk"}
# 2. 内网验证前端
curl http://localhost:18080/itdesk/health
# 预期输出: healthy
# 3. 公网验证(从任意有网络的设备)
curl https://itdesk.amanzac.com/api/health
# 预期输出: {"status":"ok","service":"wecom-it-smart-desk"}
# 4. 浏览器访问
# H5 员工端: https://itdesk.amanzac.com/itdesk/
# 坐席工作台: https://itdesk.amanzac.com/itagent/
```
### 4.3 常用运维命令
```bash
# 查看日志
docker compose -f docker-compose.nas.yml logs -f backend # 后端日志
docker compose -f docker-compose.nas.yml logs -f cloudflared # Tunnel 日志
docker compose -f docker-compose.nas.yml logs -f nginx # Nginx 日志
# 重启某个服务
docker compose -f docker-compose.nas.yml restart backend
# 停止所有服务
docker compose -f docker-compose.nas.yml down
# 更新并重启(代码更新后)
docker compose -f docker-compose.nas.yml up -d --build
```
---
## §5 企微自建应用配置
### 5.1 创建自建应用
1. 登录 [企微管理后台](https://work.weixin.qq.com/wework_admin/frame)
2. **应用管理****自建****创建应用**
3. 填写:
- 应用名称:`IT智能服务台`
- 应用logo:上传一个图标
- 可见范围:选择测试部门/人员
### 5.2 配置网页授权(OAuth2
在应用详情页 → **网页授权及JS-SDK**
| 配置项 | 填写 | 说明 |
|--------|------|------|
| 可信域名 | `itdesk.amanzac.com` | OAuth2 回调域名 |
> **验证方式**Cloudflare Tunnel 已提供 HTTPS,下载企微提供的验证文件,放到 `frontend-h5/dist/` 根目录后重新构建。
### 5.3 配置应用主页
在应用详情页 → **应用主页**
```
https://itdesk.amanzac.com/itdesk/
```
员工点击企微中的应用入口,直接打开 H5 页面。
### 5.4 配置接收消息(回调 URL)
在应用详情页 → **接收消息****设置API接收**
| 配置项 | 填写 | 说明 |
|--------|------|------|
| URL | `https://itdesk.amanzac.com/api/wecom/callback` | 企微消息推送地址 |
| Token | `wAqMCP` | 与 .env 中 WECOM_TOKEN 一致 |
| EncodingAESKey | `KQY3cEsBc3rdi3xua9rPd5WxH8kYOhyASzWZQf75aJS` | 与 .env 中一致 |
> 点击保存时,企微会向 URL 发送验证请求,后端必须正常响应才能保存成功。
### 5.5 修改 AI 机器人转人工链接
在现有 AI 机器人的 Dify 工作流中,将转人工关键字触发的链接从:
```
旧链接:https://work.weixin.qq.com/XXXX(员工服务入口)
```
改为:
```
新链接:https://itdesk.amanzac.com/itdesk/
```
> 这样员工点击转人工链接后,会跳转到 H5 自建应用页面(而非企微员工服务窗口)。
---
## §6 阶段一功能测试清单
### 6.1 基础连通性测试
| # | 测试项 | 方法 | 预期结果 | 状态 |
|---|--------|------|---------|------|
| 1 | Cloudflare Tunnel 连通 | 浏览器访问 `https://itdesk.amanzac.com/` | 页面正常加载 | ⬜ |
| 2 | 后端 API 健康 | 浏览器访问 `https://itdesk.amanzac.com/api/health` | 返回 `{"status":"ok"}` | ⬜ |
| 3 | H5 员工端页面 | 浏览器访问 `https://itdesk.amanzac.com/itdesk/` | H5 页面渲染 | ⬜ |
| 4 | 坐席工作台页面 | 浏览器访问 `https://itdesk.amanzac.com/itagent/` | 工作台页面渲染 | ⬜ |
### 6.2 OAuth2 登录测试
| # | 测试项 | 方法 | 预期结果 | 状态 |
|---|--------|------|---------|------|
| 5 | OAuth2 静默授权 | 在企微内点击应用入口 | H5 页面自动登录,显示员工身份 | ⬜ |
| 6 | 身份识别 | 授权后查看 H5 页面 | 显示当前用户姓名/工号 | ⬜ |
### 6.3 坐席工作台测试
| # | 测试项 | 方法 | 预期结果 | 状态 |
|---|--------|------|---------|------|
| 7 | 会话列表 | 坐席登录工作台 | 显示进行中的会话 | ⬜ |
| 8 | 聊天窗口 | 点击某个会话 | 显示完整对话记录 | ⬜ |
| 9 | 发送消息 | 坐席输入文本发送 | 消息发送成功 | ⬜ |
| 10 | 快速回复 | 点击快速回复面板 | 三级导航正常,模板可填入 | ⬜ |
### 6.4 端到端流程测试
| # | 测试项 | 方法 | 预期结果 | 状态 |
|---|--------|------|---------|------|
| 11 | AI 对话 → 转人工 | 员工与 AI 对话,触发转人工关键字 | 推送 H5 链接 | ⬜ |
| 12 | 员工点击 H5 链接 | 点击推送的链接 | 跳转到 H5 页面,自动登录 | ⬜ |
| 13 | 坐席收到会话 | 员工进入 H5 后 | 坐席工作台出现新会话 | ⬜ |
| 14 | 坐席回复 | 坐席使用快速回复 | 员工 H5 页面显示回复 | ⬜ |
| 15 | 企微通知 | 坐席回复后 | 员工收到企微应用消息通知 | ⬜ |
---
## §7 故障排查
### 7.1 Cloudflare Tunnel 连不上
```bash
# 检查 cloudflared 容器日志
docker compose -f docker-compose.nas.yml logs cloudflared
# 常见错误:
# ERR error="failed to connect to Cloudflare edge"
# → 检查 Token 是否正确
# → 检查 NAS 是否能访问外网
```
### 7.2 企微回调验证失败
```bash
# 检查后端是否收到回调请求
docker compose -f docker-compose.nas.yml logs backend | grep callback
# 常见原因:
# 1. Token / EncodingAESKey 与 .env 不一致
# 2. 后端回调路由路径不对(应为 /api/wecom/callback
# 3. Nginx 反代配置未正确转发
```
### 7.3 OAuth2 授权失败
```
常见原因:
1. 可信域名未配置或未验证 → 企微管理后台检查
2. redirect_uri 与可信域名不匹配 → 检查回调 URL
3. CorpID 不正确 → 检查 .env 中的 WECOM_CORP_ID
```
### 7.4 容器状态异常
```bash
# 查看所有容器状态
docker compose -f docker-compose.nas.yml ps
# 查看特定容器详细日志
docker compose -f docker-compose.nas.yml logs --tail 100 backend
# 重启所有容器
docker compose -f docker-compose.nas.yml restart
# 完全重建(代码更新后)
docker compose -f docker-compose.nas.yml down
docker compose -f docker-compose.nas.yml up -d --build
```
---
## §8 与正式部署的区别
| 维度 | NAS 部署(测试) | 正式部署 |
|------|----------------|---------|
| 域名 | `itdesk.amanzac.com` | `it-dataquery.dc.servyou-it.com` |
| 内网穿透 | Cloudflare Tunnel | 公司内网直连 |
| HTTPS | Cloudflare 自动 | Nginx + 公司 CA 证书 |
| 数据库密码 | 测试密码 | 强密码 + 审计 |
| AI 引擎 | 可能不可用(Dify 在内网) | 可用 |
| 员工数 | 测试人员(<10人) | 全公司 |
| 企业微信认证 | 未认证(200人上限) | 已认证 |
| 数据持久化 | Docker Volume | K8s PVC / 独立 PG 集群 |
---
## 附录 ACloudflare Tunnel 原理简述
```
传统方式 Cloudflare Tunnel
┌─────────────────┐ ┌─────────────────┐
互联网 ────→ │ 开放端口 + 公网IP │ 互联网 ────→ │ Cloudflare Edge │
│ + SSL 证书 │ │ (自动HTTPS) │
│ + DDNS/域名解析 │ └────────┬────────┘
└─────────────────┘ │
↑ │ Tunnel(长连接)
│ │
┌─────────────────┐ ┌─────────────────┐
│ NAS/服务器 │ cloudflared │ NAS/服务器 │
│ (必须可达) │ ←──主动连接──→│ (无需开放端口) │
└─────────────────┘ └─────────────────┘
优势:
1. 无需公网 IP — cloudflared 主动外连,不需要入站端口
2. 无需 SSL 证书 — Cloudflare Edge 自动处理 HTTPS
3. 无需 DDNS — 域名始终指向 Cloudflare
4. 更安全 — 不暴露 NAS 任何端口到公网
```