Files
wecom-ai-assistant/docs/deploy.md
2026-02-05 16:36:32 +08:00

656 lines
15 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.
# 生产环境部署指南
## 一、概述
本文档描述如何在云端服务器上部署企业微信 AI 助手的最小回调壳,支持企业微信回调 URL 校验和消息回调。
**部署架构**
```
企业微信 → HTTPS (443) → Nginx → Backend (8000)
PostgreSQL (可选)
```
**服务清单**
- `backend`: Python 3.12 + FastAPI + Uvicorn最小回调壳
- `nginx`: 反向代理 + HTTPSLet's Encrypt
- `db`: PostgreSQL 16可选最小回调壳可以先不启用
- `admin`: Next.js 管理后台(可选,最小回调壳可以先不启用)
---
## 二、云服务器准备
### 2.1 服务器要求
- **操作系统**Ubuntu 20.04+ / CentOS 7+ / Debian 11+
- **CPU**1 核以上
- **内存**1GB 以上(推荐 2GB
- **磁盘**20GB 以上
- **网络**:公网 IP开放 80/443 端口
### 2.2 安装 Docker 和 Docker Compose
#### Ubuntu/Debian
```bash
# 更新系统
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 添加 Docker 仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 将当前用户添加到 docker 组(可选,避免每次使用 sudo
sudo usermod -aG docker $USER
newgrp docker
# 验证安装
docker --version
docker compose version
```
#### CentOS/RHEL
```bash
# 安装依赖
sudo yum install -y yum-utils
# 添加 Docker 仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 启动 Docker
sudo systemctl start docker
sudo systemctl enable docker
# 将当前用户添加到 docker 组
sudo usermod -aG docker $USER
newgrp docker
# 验证安装
docker --version
docker compose version
```
### 2.3 配置防火墙
#### Ubuntu (UFW)
```bash
# 允许 SSH避免锁定
sudo ufw allow 22/tcp
# 允许 HTTP/HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# 启用防火墙
sudo ufw enable
# 检查状态
sudo ufw status
```
#### CentOS/RHEL (firewalld)
```bash
# 允许 HTTP/HTTPS
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
# 检查状态
sudo firewall-cmd --list-all
```
---
## 三、域名 DNS 配置
### 3.1 添加 A 记录
在域名服务商如阿里云、腾讯云、Cloudflare添加 A 记录:
```
类型: A
主机记录: @ 或 api例如api.yourdomain.com
记录值: 你的服务器公网 IP
TTL: 600或默认
```
### 3.2 验证 DNS 解析
```bash
# 检查 DNS 解析
nslookup your-domain.com
# 或
dig your-domain.com
# 应该返回你的服务器 IP
```
---
## 四、项目部署
### 4.1 克隆项目
```bash
# 创建项目目录
sudo mkdir -p /opt/wecom-ai-assistant
sudo chown $USER:$USER /opt/wecom-ai-assistant
cd /opt/wecom-ai-assistant
# 克隆项目(或通过 CI/CD 部署)
git clone https://github.com/your-org/wecom-ai-assistant.git .
```
### 4.2 配置环境变量
```bash
# 复制环境变量模板
cp .env.example .env.prod
# 编辑 .env.prod填写必需变量
nano .env.prod
```
**必需变量**
```bash
# ============ Backend ============
API_HOST=0.0.0.0
API_PORT=8000
# Database可选最小回调壳可以先不启用
# DATABASE_URL=postgresql+asyncpg://wecom:wecom_secret@db:5432/wecom_ai
# DATABASE_URL_SYNC=postgresql://wecom:wecom_secret@db:5432/wecom_ai
# JWTadmin 登录,可选)
JWT_SECRET=your-jwt-secret-change-in-production
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=60
# WeCom Callback必须从企业微信管理后台获取
WECOM_CORP_ID=你的企业ID
WECOM_AGENT_ID=你的应用AgentId
WECOM_SECRET=你的应用Secret可选
WECOM_TOKEN=你的Token必须与企微后台一致
WECOM_ENCODING_AES_KEY=你的43位密钥必须与企微后台一致
# WeCom API
WECOM_API_BASE=https://qyapi.weixin.qq.com
WECOM_API_TIMEOUT=10
WECOM_API_RETRIES=2
# Log
LOG_LEVEL=INFO
LOG_JSON=true
```
**重要**
- `WECOM_TOKEN``WECOM_ENCODING_AES_KEY` 必须与企微后台配置**完全一致**
- `.env.prod` 文件包含敏感信息,**不要提交到 Git 仓库**
### 4.3 首次部署
#### 方式 A使用部署脚本推荐
```bash
# 赋予执行权限
chmod +x deploy/scripts/*.sh
# 启动服务
./deploy/scripts/start.sh
```
#### 方式 B手动部署
```bash
# 设置镜像标签(默认 latest
export IMAGE_TAG=latest
export GITHUB_REPOSITORY_OWNER=your-org
# 启动服务
docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d
# 查看日志
docker-compose -f docker-compose.prod.yml logs -f backend
```
---
## 五、HTTPS 配置Let's Encrypt
### 5.1 安装 Certbot
#### Ubuntu/Debian
```bash
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
```
#### CentOS/RHEL
```bash
sudo yum install -y certbot python3-certbot-nginx
```
### 5.2 配置 Nginx 占位路径
在获取证书之前,需要先配置 Nginx 的 HTTP 服务,以便 Certbot 验证域名所有权。
**临时修改 `deploy/docker/nginx.conf`**
```nginx
# HTTP 服务器(临时配置,用于证书申请)
server {
listen 80;
server_name your-domain.com;
# Let's Encrypt 验证路径
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# /api -> backend
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 健康检查
location /health {
proxy_pass http://backend/api/health;
access_log off;
}
}
```
**创建验证目录**
```bash
sudo mkdir -p /var/www/certbot
sudo chown -R $USER:$USER /var/www/certbot
```
**更新 `docker-compose.prod.yml`**,添加验证目录挂载:
```yaml
nginx:
volumes:
- ./deploy/docker/nginx.conf:/etc/nginx/nginx.conf:ro
- /var/www/certbot:/var/www/certbot:ro # 添加此行
```
**重启 Nginx**
```bash
docker-compose -f docker-compose.prod.yml restart nginx
```
### 5.3 申请 SSL 证书
```bash
# 设置域名和邮箱
export DOMAIN=your-domain.com
export EMAIL=your-email@example.com
# 申请证书(使用 Nginx 插件)
sudo certbot certonly --nginx \
-d $DOMAIN \
-d www.$DOMAIN \
--email $EMAIL \
--agree-tos \
--non-interactive \
--preferred-challenges http
# 或使用 standalone 模式(如果 Nginx 未运行)
sudo certbot certonly --standalone \
-d $DOMAIN \
-d www.$DOMAIN \
--email $EMAIL \
--agree-tos \
--non-interactive
```
### 5.4 更新 Nginx 配置
证书申请成功后,更新 `deploy/docker/nginx.conf`
```nginx
# HTTPS 服务器
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL 证书(使用实际域名替换 _
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# ... 其他配置
}
```
**更新 `docker-compose.prod.yml`**,确保证书目录已挂载:
```yaml
nginx:
volumes:
- ./deploy/docker/nginx.conf:/etc/nginx/nginx.conf:ro
- /etc/letsencrypt:/etc/letsencrypt:ro # SSL 证书
- /var/www/certbot:/var/www/certbot:ro # 验证文件
```
**重启 Nginx**
```bash
docker-compose -f docker-compose.prod.yml restart nginx
```
### 5.5 配置证书自动续期
Let's Encrypt 证书有效期为 90 天,需要定期续期。
```bash
# 测试续期
sudo certbot renew --dry-run
# 添加定时任务(每天检查一次)
sudo crontab -e
# 添加以下行:
0 0 * * * certbot renew --quiet --deploy-hook "docker-compose -f /opt/wecom-ai-assistant/docker-compose.prod.yml restart nginx"
```
---
## 六、部署命令
### 6.1 首次部署
```bash
# 使用部署脚本
./deploy/scripts/start.sh
# 或手动部署
docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d
```
### 6.2 更新部署
#### 方式 A使用部署脚本
```bash
# 更新到最新版本
./deploy/scripts/update.sh latest
# 更新到指定版本
./deploy/scripts/update.sh v1.0.0
```
#### 方式 B手动更新
```bash
# 设置镜像标签
export IMAGE_TAG=latest # 或指定版本,如 v1.0.0
# 登录到容器镜像仓库
docker login ghcr.io -u your-username -p your-token
# 拉取最新镜像
docker-compose -f docker-compose.prod.yml --env-file .env.prod pull
# 重启服务
docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d
```
### 6.3 回滚部署
```bash
# 回滚到指定版本(需要知道之前的镜像标签)
export IMAGE_TAG=v0.9.0 # 替换为要回滚的版本
# 拉取指定版本镜像
docker-compose -f docker-compose.prod.yml --env-file .env.prod pull
# 重启服务
docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d
```
**查看历史版本**
```bash
# 查看 GitHub Container Registry 中的镜像标签
# 访问: https://github.com/your-org/wecom-ai-assistant/pkgs/container/wecom-ai-backend
```
### 6.4 停止服务
```bash
# 使用部署脚本
./deploy/scripts/stop.sh
# 或手动停止
docker-compose -f docker-compose.prod.yml --env-file .env.prod down
```
---
## 七、验证部署
### 7.1 检查服务状态
```bash
# 查看服务状态
docker-compose -f docker-compose.prod.yml ps
# 查看日志
docker-compose -f docker-compose.prod.yml logs -f backend
```
### 7.2 健康检查
```bash
# HTTP 健康检查(如果 HTTPS 未配置)
curl http://your-domain.com/api/health
# HTTPS 健康检查(推荐)
curl https://your-domain.com/api/health
# 应该返回:
# {"status":"ok"}
```
### 7.3 企业微信回调验证
1. **配置企业微信回调 URL**
- 登录企业微信管理后台https://work.weixin.qq.com
- 进入:应用管理 → 自建应用 → 选择你的应用
- 配置回调:
- **接收消息服务器 URL**`https://your-domain.com/api/wecom/callback`
- **Token**:与 `.env.prod` 中的 `WECOM_TOKEN` **完全一致**
- **EncodingAESKey**:与 `.env.prod` 中的 `WECOM_ENCODING_AES_KEY` **完全一致**
- **消息加解密方式****安全模式**
- 点击 **保存**
2. **验证 GET 校验**
- 保存后,企业微信会立即发送 GET 请求验证
- 观察后端日志:
```bash
docker-compose -f docker-compose.prod.yml logs -f backend
```
- 应该看到:
```
INFO: wecom verify success {"trace_id": "...", "echostr_length": 43}
```
3. **验证 POST 回调**
- 在企业微信中发送测试消息
- 观察后端日志,应该看到:
```
INFO: wecom message received {"trace_id": "...", "external_userid": "...", "msgid": "...", "content_summary": "..."}
INFO: wecom reply sent {"trace_id": "...", "reply_summary": "..."}
```
---
## 八、GitHub Actions 自动部署
### 8.1 配置 GitHub Secrets
在 GitHub 仓库设置中添加以下 Secrets
| Secret 名称 | 说明 | 示例 |
|------------|------|------|
| `PROD_HOST` | 生产服务器 IP 或域名 | `123.45.67.89` |
| `PROD_USER` | SSH 用户名 | `ubuntu` |
| `PROD_SSH_KEY` | SSH 私钥 | `-----BEGIN OPENSSH PRIVATE KEY-----...` |
| `PROD_SSH_PORT` | SSH 端口(可选,默认 22 | `22` |
| `PROD_DOMAIN` | 生产域名 | `api.yourdomain.com` |
| `PROD_APP_PATH` | 应用部署路径(可选) | `/opt/wecom-ai-assistant` |
### 8.2 生成 SSH 密钥对
```bash
# 在本地生成 SSH 密钥对
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github-actions-deploy
# 将公钥添加到服务器
ssh-copy-id -i ~/.ssh/github-actions-deploy.pub user@your-server
# 将私钥内容复制到 GitHub Secrets
cat ~/.ssh/github-actions-deploy
```
### 8.3 自动部署流程
1. **推送代码到 main 分支**
```bash
git push origin main
```
2. **GitHub Actions 自动执行**
- 构建 backend 镜像
- 推送到 GHCR
- SSH 到生产服务器
- 拉取最新镜像
- 重启服务
- 健康检查
3. **查看部署日志**
- 访问 GitHub Actions`https://github.com/your-org/wecom-ai-assistant/actions`
---
## 九、常见问题
### 9.1 服务启动失败
**症状**`docker-compose ps` 显示服务状态为 `Restarting` 或 `Exited`
**排查**
```bash
# 查看详细日志
docker-compose -f docker-compose.prod.yml logs backend
# 检查环境变量
docker-compose -f docker-compose.prod.yml config
```
**常见原因**
- 环境变量未正确配置
- 端口被占用
- 镜像拉取失败
### 9.2 HTTPS 证书问题
**症状**:浏览器显示"不安全连接"或证书错误
**排查**
```bash
# 检查证书
sudo certbot certificates
# 检查证书有效期
sudo openssl x509 -in /etc/letsencrypt/live/your-domain.com/cert.pem -noout -dates
# 测试续期
sudo certbot renew --dry-run
```
### 9.3 企业微信回调失败
**症状**:企微后台保存失败,日志显示 `wecom verify failed`
**排查**
1. 检查 `.env.prod` 中的 `WECOM_TOKEN` 和 `WECOM_ENCODING_AES_KEY`
2. 确保与企微后台配置**完全一致**(包括大小写、空格)
3. 检查域名是否可访问:`curl https://your-domain.com/api/wecom/callback`
4. 查看后端日志:`docker-compose -f docker-compose.prod.yml logs backend`
### 9.4 镜像拉取失败
**症状**`docker pull` 失败,提示认证错误
**解决**
```bash
# 登录到 GHCR
docker login ghcr.io -u your-username -p your-token
# 或使用 GitHub Personal Access Token
echo $GITHUB_TOKEN | docker login ghcr.io -u your-username --password-stdin
```
---
## 十、安全最佳实践
1. **环境变量**
- 使用 `.env.prod` 存储敏感信息
- **不要提交 `.env.prod` 到 Git 仓库**
- 定期轮换密钥和 Token
2. **SSH 安全**
- 使用密钥认证,禁用密码登录
- 限制 SSH 访问 IP可选
- 定期更新 SSH 密钥
3. **防火墙**
- 只开放必要的端口80, 443, 22
- 使用 fail2ban 防止暴力破解(可选)
4. **日志**
- 定期清理日志文件
- 监控异常日志
5. **更新**
- 定期更新系统和 Docker
- 及时应用安全补丁
---
## 十一、参考文档
- [本地部署指南](./deploy-cloud-minimal.md)
- [企业微信回调配置](./wecom.md)
- [企业微信测试指南](./wecom-test-guide.md)
- [GitHub Actions 部署 Workflow](../.github/workflows/deploy.yml)