Files
zclaw_openfang/docs/deployment/saas-production.md
iven d0ae7d2770 feat(deploy): add Dockerfile, saas-env.example, nginx config, and production deployment guide
Multi-stage Docker build for zclaw-saas with dependency caching,
environment variable template with security defaults, Nginx reverse
proxy with SSE/WebSocket support and HTTPS, and comprehensive
Chinese-language production deployment documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 10:26:30 +08:00

430 lines
11 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.

# ZCLAW SaaS 生产环境部署指南
本指南覆盖 ZCLAW SaaS 后端的生产环境部署,包括 Docker 容器化、Nginx 反向代理、HTTPS 配置、安全加固和备份策略。
---
## 1. 环境要求
| 组件 | 最低版本 | 说明 |
|------------|-----------|------------------------------|
| Docker | 24.0+ | 容器运行时 |
| Docker Compose | v2.0+ | 容器编排 |
| Nginx | 1.24+ | 反向代理 + TLS 终止 |
| PostgreSQL | 16+ | 数据库Docker 内置或外部) |
| RAM | 2 GB+ | 最低内存 |
| Disk | 20 GB+ | 数据库 + 日志空间 |
### 端口规划
| 端口 | 用途 | 暴露方式 |
|-------|------------------------|--------------|
| 80 | HTTP (Nginx) | 外部 -> Nginx |
| 443 | HTTPS (Nginx) | 外部 -> Nginx |
| 8080 | SaaS 后端 (Axum) | 仅本地回环 |
| 5432 | PostgreSQL | 仅 Docker 网络 |
---
## 2. 快速启动 (Docker Compose)
### 2.1 克隆仓库并配置环境变量
```bash
git clone https://github.com/zclaw/zclaw.git
cd zclaw
# 从模板创建环境变量文件
cp saas-env.example .env
```
### 2.2 编辑 `.env` 填入真实值
```bash
# 必须修改的变量:
# - POSTGRES_PASSWORD 数据库密码
# - ZCLAW_DATABASE_URL 连接字符串(密码需与上面一致)
# - ZCLAW_SAAS_JWT_SECRET JWT 密钥openssl rand -hex 32
# - ZCLAW_TOTP_ENCRYPTION_KEY 加密密钥openssl rand -hex 32
# - ZCLAW_ADMIN_PASSWORD 管理员密码
# 生成随机密钥
export JWT_SECRET=$(openssl rand -hex 32)
export TOTP_KEY=$(openssl rand -hex 32)
# 使用 sed 替换(或手动编辑)
sed -i "s/请使用openssl_rand_hex_32生成/$JWT_SECRET/" .env
sed -i "0,/请使用openssl_rand_hex_32生成/s//$TOTP_KEY/" .env
```
### 2.3 启动服务
```bash
# 构建并启动(后台运行)
docker compose up -d --build
# 查看日志
docker compose logs -f saas
# 验证服务健康
curl http://localhost:8080/health
```
### 2.4 常用运维命令
```bash
# 停止服务
docker compose down
# 重启 SaaS 后端(不影响数据库)
docker compose restart saas
# 查看数据库状态
docker compose exec postgres pg_isready -U zclaw
# 进入数据库
docker compose exec postgres psql -U zclaw -d zclaw_saas
# 查看资源使用
docker stats zclaw-saas zclaw-postgres
```
---
## 3. 环境变量配置
### 3.1 核心变量
| 变量 | 必填 | 说明 |
|----------------------------|------|------------------------------------------|
| `POSTGRES_USER` | 是 | 数据库用户名 |
| `POSTGRES_PASSWORD` | 是 | 数据库密码 |
| `POSTGRES_DB` | 是 | 数据库名称 |
| `ZCLAW_DATABASE_URL` | 是 | 完整数据库连接 URL |
| `ZCLAW_SAAS_JWT_SECRET` | 是 | JWT 签名密钥(>= 32 字符随机字符串) |
| `ZCLAW_TOTP_ENCRYPTION_KEY`| 是 | TOTP/API Key 加密密钥64 字符 hex |
| `ZCLAW_ADMIN_USERNAME` | 否 | 初始管理员用户名(默认 admin |
| `ZCLAW_ADMIN_PASSWORD` | 否 | 初始管理员密码 |
| `ZCLAW_SAAS_DEV` | 否 | 开发模式标志(生产环境必须 false 或不设置) |
### 3.2 连接 URL 格式
```
postgres://<用户名>:<密码>@<主机>:<端口>/<数据库名>
```
Docker 内部网络使用主机名 `postgres`
```
ZCLAW_DATABASE_URL=postgres://zclaw:your_password@postgres:5432/zclaw_saas
```
外部 PostgreSQL 使用实际 IP/域名:
```
ZCLAW_DATABASE_URL=postgres://zclaw:your_password@10.0.0.5:5432/zclaw_saas
```
### 3.3 saas-config.toml 配置
`saas-config.toml` 提供默认配置,环境变量优先级更高:
```toml
[server]
host = "0.0.0.0"
port = 8080
cors_origins = ["https://your-domain.com"]
[database]
url = "postgres://zclaw:${DB_PASSWORD}@localhost:5432/zclaw"
[auth]
jwt_expiration_hours = 24
totp_issuer = "ZCLAW SaaS"
[rate_limit]
requests_per_minute = 60
burst = 10
```
配置支持 `${ENV_VAR}` 环境变量插值。
---
## 4. Nginx 反向代理 + HTTPS
### 4.1 安装 Nginx
```bash
sudo apt update && sudo apt install -y nginx
```
### 4.2 获取 SSL 证书 (Let's Encrypt)
```bash
# 安装 certbot
sudo apt install -y certbot python3-certbot-nginx
# 获取证书(替换为你的域名和邮箱)
sudo certbot --nginx -d api.yourdomain.com -m admin@yourdomain.com --agree-tos
```
### 4.3 配置 Nginx
```bash
# 复制配置模板
sudo cp deploy/nginx.conf /etc/nginx/sites-available/zclaw-saas
# 替换占位符
sudo sed -i 's/<YOUR_DOMAIN>/api.yourdomain.com/g' /etc/nginx/sites-available/zclaw-saas
sudo sed -i 's|<CERT_PATH>|/etc/letsencrypt/live/api.yourdomain.com/fullchain.pem|g' /etc/nginx/sites-available/zclaw-saas
sudo sed -i 's|<KEY_PATH>|/etc/letsencrypt/live/api.yourdomain.com/privkey.pem|g' /etc/nginx/sites-available/zclaw-saas
# 启用站点
sudo ln -sf /etc/nginx/sites-available/zclaw-saas /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
# 验证配置
sudo nginx -t
# 重载 Nginx
sudo systemctl reload nginx
```
### 4.4 自动续期
Let's Encrypt 证书有效期为 90 天certbot 会自动设置定时续期:
```bash
# 验证续期定时器
sudo systemctl status certbot.timer
# 手动测试续期
sudo certbot renew --dry-run
```
### 4.5 SSE / WebSocket 注意事项
Nginx 配置中已包含 SSE 流式响应支持:
- `proxy_buffering off` - 禁用缓冲,确保事件实时推送
- `proxy_read_timeout 300s` - 5 分钟超时,支持长连接
- `Upgrade` / `Connection` 头 - 支持 WebSocket 升级
如果需要更长的流式响应时间,调大 `proxy_read_timeout`
---
## 5. 安全清单
### 5.1 部署前必检
- [ ] 所有密码/密钥已替换为强随机值(非模板默认值)
- [ ] `ZCLAW_SAAS_DEV` 未设置或设为 `false`
- [ ] `cors_origins` 仅包含实际域名(不含 localhost
- [ ] PostgreSQL 端口 (5432) 未暴露到公网
- [ ] SaaS 后端端口 (8080) 仅绑定 127.0.0.1
- [ ] SSL 证书已配置且有效
- [ ] Nginx 安全头已启用X-Frame-Options, HSTS 等)
- [ ] `.env` 文件权限设为 600`chmod 600 .env`
### 5.2 Cookie 安全
| 属性 | 开发环境 | 生产环境 |
|---------------|---------|---------|
| `Secure` | false | true |
| `HttpOnly` | true | true |
| `SameSite` | Strict | Strict |
| Path | /api | /api |
### 5.3 Rate Limiting
内置 API 请求限流:
- `/api/auth/login` - 5 次/分钟/IP防暴力破解
- `/api/auth/register` - 3 次/小时/IP防刷注册
- 公共端点 - 20 次/分钟/IP防滥用
### 5.4 防火墙配置
```bash
# 仅开放必要端口
sudo ufw default deny incoming
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
```
### 5.5 日志审计
生产环境建议将日志写入文件并配置日志轮转:
```bash
# Nginx 日志轮转(通常已内置)
sudo vim /etc/logrotate.d/nginx
```
---
## 6. 备份策略
### 6.1 数据库备份
```bash
# 手动备份
docker compose exec postgres pg_dump -U zclaw zclaw_saas > backup_$(date +%Y%m%d_%H%M%S).sql
# 自动每日备份crontab
# 每天凌晨 3 点备份
echo "0 3 * * * docker compose -f /path/to/zclaw/docker-compose.yml exec -T postgres pg_dump -U zclaw zclaw_saas | gzip > /path/to/backups/zclaw_\$(date +\%Y\%m\%d).sql.gz" | crontab -
```
### 6.2 恢复数据库
```bash
# 从备份恢复
gunzip -c /path/to/backups/zclaw_20260331.sql.gz | \
docker compose exec -T postgres psql -U zclaw -d zclaw_saas
```
### 6.3 环境变量备份
```bash
# 安全存储 .env 文件
cp .env /path/to/backups/env_$(date +%Y%m%d)
chmod 600 /path/to/backups/env_*
```
### 6.4 备份保留策略
| 备份类型 | 保留期限 | 频率 |
|-----------|-----------|---------|
| 每日备份 | 7 天 | 每天一次 |
| 每周备份 | 4 周 | 每周日 |
| 每月备份 | 12 个月 | 每月 1 日 |
---
## 7. 常见问题
### 7.1 服务无法启动
**症状**: `docker compose up` 后 saas 容器立即退出
**排查步骤**:
```bash
# 查看容器日志
docker compose logs saas
# 检查环境变量是否正确
docker compose config
# 检查数据库是否就绪
docker compose exec postgres pg_isready -U zclaw
```
**常见原因**:
- 数据库 URL 格式错误
- JWT 密钥未设置
- PostgreSQL 尚未就绪healthcheck 未通过)
### 7.2 数据库连接失败
**症状**: 日志显示 `connection refused``authentication failed`
**排查步骤**:
```bash
# 检查数据库容器状态
docker compose ps postgres
# 验证连接字符串
docker compose exec saas env | grep DATABASE_URL
# 测试数据库连接
docker compose exec postgres psql -U zclaw -d zclaw_saas -c "SELECT 1"
```
### 7.3 502 Bad Gateway
**症状**: Nginx 返回 502 错误
**排查步骤**:
```bash
# 检查 SaaS 后端是否运行
curl http://127.0.0.1:8080/health
# 检查 Nginx 错误日志
sudo tail -50 /var/log/nginx/zclaw-saas-error.log
# 检查端口绑定
ss -tlnp | grep 8080
```
### 7.4 SSE 流式响应中断
**症状**: 聊天响应在中间断开
**解决方案**:
- 确认 Nginx `proxy_buffering off` 已设置
- 增大 `proxy_read_timeout`(默认 300s
- 检查 Nginx 错误日志是否有 upstream timeout
### 7.5 Docker 构建缓慢
**症状**: `docker build` 耗时很长
**优化**:
- Dockerfile 已配置依赖缓存层,首次构建后仅重建源码变更
- 确保 `.dockerignore` 排除了 `target/``node_modules/` 等大目录
- 使用 `docker compose build --parallel` 并行构建
### 7.6 磁盘空间不足
```bash
# 查看 Docker 磁盘使用
docker system df
# 清理未使用的资源
docker system prune -a --volumes
# 查看数据库大小
docker compose exec postgres psql -U zclaw -c "SELECT pg_size_pretty(pg_database_size('zclaw_saas'));"
```
---
## 附录: 完整部署检查清单
```
[ ] 1. 服务器准备
[ ] 2GB+ RAM, 20GB+ 磁盘
[ ] Docker + Docker Compose 已安装
[ ] 防火墙已配置(仅 22/80/443
[ ] 2. 应用配置
[ ] .env 已从模板创建并填入真实值
[ ] 所有密钥已用 openssl rand -hex 32 生成
[ ] ZCLAW_SAAS_DEV=false
[ ] saas-config.toml cors_origins 已更新
[ ] 3. 启动服务
[ ] docker compose up -d --build 成功
[ ] docker compose ps 显示所有容器 healthy
[ ] curl http://localhost:8080/health 返回 200
[ ] 4. HTTPS 配置
[ ] SSL 证书已获取
[ ] Nginx 配置已部署并测试 (nginx -t)
[ ] HTTP 正确重定向到 HTTPS
[ ] https://api.yourdomain.com/health 返回 200
[ ] 5. 安全验证
[ ] 安全头存在curl -I https://api.yourdomain.com
[ ] 5432 端口外部不可访问
[ ] 8080 端口仅 127.0.0.1 可访问
[ ] .env 文件权限 600
[ ] 6. 备份
[ ] 数据库自动备份已配置
[ ] 备份恢复测试已通过
```