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

11 KiB
Raw Blame History

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 克隆仓库并配置环境变量

git clone https://github.com/zclaw/zclaw.git
cd zclaw

# 从模板创建环境变量文件
cp saas-env.example .env

2.2 编辑 .env 填入真实值

# 必须修改的变量:
# - 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 启动服务

# 构建并启动(后台运行)
docker compose up -d --build

# 查看日志
docker compose logs -f saas

# 验证服务健康
curl http://localhost:8080/health

2.4 常用运维命令

# 停止服务
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 提供默认配置,环境变量优先级更高:

[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

sudo apt update && sudo apt install -y nginx

4.2 获取 SSL 证书 (Let's Encrypt)

# 安装 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

# 复制配置模板
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 会自动设置定时续期:

# 验证续期定时器
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 文件权限设为 600chmod 600 .env
属性 开发环境 生产环境
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 防火墙配置

# 仅开放必要端口
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 日志审计

生产环境建议将日志写入文件并配置日志轮转:

# Nginx 日志轮转(通常已内置)
sudo vim /etc/logrotate.d/nginx

6. 备份策略

6.1 数据库备份

# 手动备份
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 恢复数据库

# 从备份恢复
gunzip -c /path/to/backups/zclaw_20260331.sql.gz | \
    docker compose exec -T postgres psql -U zclaw -d zclaw_saas

6.3 环境变量备份

# 安全存储 .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 容器立即退出

排查步骤:

# 查看容器日志
docker compose logs saas

# 检查环境变量是否正确
docker compose config

# 检查数据库是否就绪
docker compose exec postgres pg_isready -U zclaw

常见原因:

  • 数据库 URL 格式错误
  • JWT 密钥未设置
  • PostgreSQL 尚未就绪healthcheck 未通过)

7.2 数据库连接失败

症状: 日志显示 connection refusedauthentication failed

排查步骤:

# 检查数据库容器状态
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 错误

排查步骤:

# 检查 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 磁盘空间不足

# 查看 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. 备份
    [ ] 数据库自动备份已配置
    [ ] 备份恢复测试已通过