# 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//api.yourdomain.com/g' /etc/nginx/sites-available/zclaw-saas sudo sed -i 's||/etc/letsencrypt/live/api.yourdomain.com/fullchain.pem|g' /etc/nginx/sites-available/zclaw-saas sudo sed -i 's||/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. 备份 [ ] 数据库自动备份已配置 [ ] 备份恢复测试已通过 ```