Files
zclaw_openfang/docs/deployment/saas-deployment.md
iven 44256a511c feat: 增强SaaS后端功能与安全性
refactor: 重构数据库连接使用PostgreSQL替代SQLite
feat(auth): 增加JWT验证的audience和issuer检查
feat(crypto): 添加AES-256-GCM字段加密支持
feat(api): 集成utoipa实现OpenAPI文档
fix(admin): 修复配置项表单验证逻辑
style: 统一代码格式与类型定义
docs: 更新技术栈文档说明PostgreSQL
2026-03-31 00:12:53 +08:00

194 lines
4.4 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.

# ZCLAW SaaS 后端部署指南
## 系统要求
| 组件 | 最低要求 | 推荐配置 |
|------|---------|---------|
| CPU | 2 核 | 4 核 |
| 内存 | 2 GB | 4 GB |
| 磁盘 | 10 GB SSD | 20 GB SSD |
| PostgreSQL | 15+ | 16 |
| Docker | 24+ | 最新 |
## 快速部署 (Docker Compose)
### 1. 准备配置
```bash
# 进入项目目录
cd zclaw-saas
# 复制环境变量模板
cp saas-env.example .env
# 编辑 .env填入实际值
# 必须修改: POSTGRES_PASSWORD, ZCLAW_SAAS_JWT_SECRET, ZCLAW_SAAS_FIELD_ENCRYPTION_KEY
```
### 2. 生成密钥
```bash
# JWT 密钥
openssl rand -base64 48
# AES-256-GCM 字段加密密钥
openssl rand -hex 32
```
### 3. 配置 CORS
编辑 `saas-config.toml`,设置允许的来源:
```toml
[server]
cors_origins = ["https://your-admin-domain.com", "https://your-app-domain.com"]
```
### 4. 启动服务
```bash
# 构建并启动
docker compose up -d --build
# 查看日志
docker compose logs -f saas
# 查看状态
docker compose ps
```
### 5. 验证部署
```bash
# 健康检查
curl http://localhost:8080/health
# API 版本
curl http://localhost:8080/api/v1/relay/models
```
## 手动部署 (无 Docker)
### 1. 安装依赖
- Rust 1.75+ (推荐 rustup)
- PostgreSQL 16
- OpenSSL 开发头文件 (`libssl-dev` on Ubuntu)
### 2. 数据库初始化
```bash
# 创建数据库
createdb zclaw
# 启动 SaaS 服务 (首次启动自动创建表结构)
ZCLAW_SAAS_JWT_SECRET=xxx \
ZCLAW_SAAS_FIELD_ENCRYPTION_KEY=xxx \
DATABASE_URL=postgres://user:pass@localhost:5432/zclaw \
cargo run --release --package zclaw-saas
```
### 3. 环境变量
| 变量 | 必需 | 说明 |
|------|------|------|
| `DATABASE_URL` | 是 | PostgreSQL 连接 URL |
| `ZCLAW_SAAS_JWT_SECRET` | 是 | JWT 签名密钥 (>=32 字符) |
| `ZCLAW_SAAS_FIELD_ENCRYPTION_KEY` | 是* | AES-256-GCM 密钥 (64 字符 hex) |
| `ZCLAW_SAAS_CONFIG` | 否 | 配置文件路径 (默认 `./saas-config.toml`) |
| `ZCLAW_SAAS_DEV` | 否 | 开发模式 (`true`/`1`) |
*生产环境必需。开发环境设置 `ZCLAW_SAAS_DEV=true` 可自动生成临时密钥。
### 4. 配置文件 (saas-config.toml)
```toml
[server]
host = "0.0.0.0"
port = 8080
cors_origins = ["https://admin.example.com"]
[database]
url = "postgres://user:pass@localhost:5432/zclaw"
[auth]
jwt_expiration_hours = 24
totp_issuer = "ZCLAW SaaS"
[relay]
max_queue_size = 1000
max_concurrent_per_provider = 5
batch_window_ms = 50
retry_delay_ms = 1000
max_attempts = 3
[rate_limit]
requests_per_minute = 60
burst = 10
```
## 安全加固清单
- [ ] `ZCLAW_SAAS_JWT_SECRET` 使用强随机密钥
- [ ] `ZCLAW_SAAS_FIELD_ENCRYPTION_KEY` 已设置 (数据库 API Key 加密)
- [ ] `ZCLAW_SAAS_DEV` 未设置或为 `false`
- [ ] `cors_origins` 配置为实际域名
- [ ] PostgreSQL 使用独立密码,不使用默认密码
- [ ] 防火墙仅开放 8080 端口
- [ ] HTTPS 反向代理 (Nginx/Caddy) 配置在 SaaS 前面
## Nginx 反向代理示例
```nginx
server {
listen 443 ssl;
server_name saas-api.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
# SSE 超时设置
proxy_read_timeout 300s;
proxy_buffering off;
}
}
```
## 运维命令
```bash
# 使用 Makefile
make saas-build # 编译
make saas-run # 启动
make saas-test # 运行测试
make saas-clippy # 代码检查
make saas-docker-up # Docker 启动
make saas-docker-down # Docker 停止
# 或手动
cargo build --release --package zclaw-saas
cargo run --release --package zclaw-saas
cargo test --package zclaw-saas
cargo clippy --package zclaw-saas
```
## 故障排查
| 问题 | 排查步骤 |
|------|---------|
| 启动失败 "DATABASE_URL 未配置" | 检查 `.env``DATABASE_URL` 是否设置 |
| 启动失败 "ZCLAW_SAAS_JWT_SECRET 未设置" | 设置环境变量或 `ZCLAW_SAAS_DEV=true` |
| 请求 429 Too Many Requests | 调整 `saas-config.toml``rate_limit` 配置 |
| 中转 502 Bad Gateway | 检查 provider URL 是否可达、API Key 是否有效 |
| SSE 流中断 | 检查反向代理超时设置,确保 `proxy_read_timeout >= 300s` |