From d0ae7d2770a41d5f3869c5d74b8c1d024ff96aaa Mon Sep 17 00:00:00 2001 From: iven Date: Tue, 31 Mar 2026 10:26:30 +0800 Subject: [PATCH] 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 --- Dockerfile | 106 +++++++ deploy/nginx.conf | 110 ++++++++ docs/deployment/saas-production.md | 429 +++++++++++++++++++++++++++++ saas-env.example | 35 +++ 4 files changed, 680 insertions(+) create mode 100644 Dockerfile create mode 100644 deploy/nginx.conf create mode 100644 docs/deployment/saas-production.md create mode 100644 saas-env.example diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2058171 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,106 @@ +# ============================================================ +# ZCLAW SaaS Backend - Multi-stage Docker Build +# ============================================================ +# Build: docker build -t zclaw-saas . +# Run: docker run --env-file saas-env.example zclaw-saas +# ============================================================ +# +# .dockerignore recommended contents: +# target/ +# node_modules/ +# desktop/ +# admin/ +# admin-v2/ +# docs/ +# .git/ +# .claude/ +# *.md +# *.pen +# plans/ +# dist/ +# pencil-new.pen +# ============================================================ + +# ---- Stage 1: Build ---- +FROM rust:1.85-bookworm AS builder + +WORKDIR /usr/src/zclaw + +# Cache dependency builds by copying manifests first +COPY Cargo.toml Cargo.lock ./ + +# Create dummy lib.rs files so cargo can resolve the workspace +RUN mkdir -p crates/zclaw-types/src && echo "" > crates/zclaw-types/src/lib.rs +RUN mkdir -p crates/zclaw-memory/src && echo "" > crates/zclaw-memory/src/lib.rs +RUN mkdir -p crates/zclaw-runtime/src && echo "" > crates/zclaw-runtime/src/lib.rs +RUN mkdir -p crates/zclaw-kernel/src && echo "" > crates/zclaw-kernel/src/lib.rs +RUN mkdir -p crates/zclaw-skills/src && echo "" > crates/zclaw-skills/src/lib.rs +RUN mkdir -p crates/zclaw-hands/src && echo "" > crates/zclaw-hands/src/lib.rs +RUN mkdir -p crates/zclaw-protocols/src && echo "" > crates/zclaw-protocols/src/lib.rs +RUN mkdir -p crates/zclaw-pipeline/src && echo "" > crates/zclaw-pipeline/src/lib.rs +RUN mkdir -p crates/zclaw-growth/src && echo "" > crates/zclaw-growth/src/lib.rs +RUN mkdir -p crates/zclaw-saas/src && echo "fn main() {}" > crates/zclaw-saas/src/main.rs +RUN mkdir -p desktop/src-tauri/src && echo "" > desktop/src-tauri/src/lib.rs + +# Copy all crate Cargo.toml files for dependency resolution +COPY crates/zclaw-types/Cargo.toml crates/zclaw-types/Cargo.toml +COPY crates/zclaw-memory/Cargo.toml crates/zclaw-memory/Cargo.toml +COPY crates/zclaw-runtime/Cargo.toml crates/zclaw-runtime/Cargo.toml +COPY crates/zclaw-kernel/Cargo.toml crates/zclaw-kernel/Cargo.toml +COPY crates/zclaw-skills/Cargo.toml crates/zclaw-skills/Cargo.toml +COPY crates/zclaw-hands/Cargo.toml crates/zclaw-hands/Cargo.toml +COPY crates/zclaw-protocols/Cargo.toml crates/zclaw-protocols/Cargo.toml +COPY crates/zclaw-pipeline/Cargo.toml crates/zclaw-pipeline/Cargo.toml +COPY crates/zclaw-growth/Cargo.toml crates/zclaw-growth/Cargo.toml +COPY crates/zclaw-saas/Cargo.toml crates/zclaw-saas/Cargo.toml +COPY desktop/src-tauri/Cargo.toml desktop/src-tauri/Cargo.toml + +# Build dependencies only (cached layer) +RUN cargo build --release -p zclaw-saas 2>/dev/null || true + +# Now copy the actual source code +COPY crates/ crates/ +COPY desktop/src-tauri/src/ desktop/src-tauri/src/ + +# Touch source files to invalidate cache after dependency layer +RUN find crates/zclaw-saas/src -type f -exec touch {} + + +# Build the final binary +RUN cargo build --release -p zclaw-saas + +# ---- Stage 2: Runtime ---- +FROM debian:bookworm-slim + +# Install runtime dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Create non-root user for security +RUN groupadd --gid 1000 zclaw && \ + useradd --uid 1000 --gid zclaw --shell /bin/bash --create-home zclaw + +WORKDIR /app + +# Copy binary from builder +COPY --from=builder /usr/src/zclaw/target/release/zclaw-saas ./zclaw-saas + +# Copy default config (can be overridden by env vars) +COPY saas-config.toml ./saas-config.toml + +# Set ownership +RUN chown -R zclaw:zclaw /app + +# Switch to non-root user +USER zclaw + +# Expose SaaS backend port +EXPOSE 8080 + +# Health check +HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ + CMD curl -f http://localhost:8080/health || exit 1 + +ENTRYPOINT ["./zclaw-saas"] diff --git a/deploy/nginx.conf b/deploy/nginx.conf new file mode 100644 index 0000000..4e86f6a --- /dev/null +++ b/deploy/nginx.conf @@ -0,0 +1,110 @@ +# ============================================================ +# ZCLAW SaaS Backend - Nginx Reverse Proxy Configuration +# ============================================================ +# Prerequisites: +# - SSL certificate (e.g., Let's Encrypt certbot) +# - Nginx installed (apt install nginx) +# +# Installation: +# sudo cp deploy/nginx.conf /etc/nginx/sites-available/zclaw-saas +# sudo ln -s /etc/nginx/sites-available/zclaw-saas /etc/nginx/sites-enabled/ +# sudo nginx -t && sudo systemctl reload nginx +# +# Replace placeholders: +# - e.g., api.zclaw.com +# - e.g., /etc/letsencrypt/live/api.zclaw.com/fullchain.pem +# - e.g., /etc/letsencrypt/live/api.zclaw.com/privkey.pem +# ============================================================ + +# ---- HTTP -> HTTPS Redirect ---- +server { + listen 80; + listen [::]:80; + server_name ; + + # Let's Encrypt challenge (keep if using certbot) + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + location / { + return 301 https://$host$request_uri; + } +} + +# ---- HTTPS Server ---- +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name ; + + # ---- SSL Configuration ---- + ssl_certificate ; + ssl_certificate_key ; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 1d; + + # ---- Security Headers ---- + add_header X-Frame-Options DENY always; + add_header X-Content-Type-Options nosniff always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; + add_header Referrer-Policy strict-origin-when-cross-origin always; + + # ---- Gzip Compression ---- + gzip on; + gzip_types + application/json + application/javascript + text/plain + text/css + text/xml + text/javascript; + gzip_min_length 256; + gzip_proxied any; + gzip_vary on; + + # ---- Request Size Limit ---- + client_max_body_size 10m; + + # ---- Proxy to ZCLAW SaaS Backend ---- + location / { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + + # ---- WebSocket / SSE Support ---- + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # ---- Standard Proxy Headers ---- + 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 Streaming Support ---- + # Disable buffering for Server-Sent Events + proxy_buffering off; + proxy_cache off; + + # Long timeout for streaming responses (5 minutes) + proxy_read_timeout 300s; + proxy_send_timeout 300s; + + # Disable request buffering for large payloads + proxy_request_buffering off; + } + + # ---- Health Check Endpoint (no logging) ---- + location = /health { + proxy_pass http://127.0.0.1:8080/health; + access_log off; + } + + # ---- Logging ---- + access_log /var/log/nginx/zclaw-saas-access.log; + error_log /var/log/nginx/zclaw-saas-error.log warn; +} diff --git a/docs/deployment/saas-production.md b/docs/deployment/saas-production.md new file mode 100644 index 0000000..53d03fd --- /dev/null +++ b/docs/deployment/saas-production.md @@ -0,0 +1,429 @@ +# 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. 备份 + [ ] 数据库自动备份已配置 + [ ] 备份恢复测试已通过 +``` diff --git a/saas-env.example b/saas-env.example new file mode 100644 index 0000000..b1fce84 --- /dev/null +++ b/saas-env.example @@ -0,0 +1,35 @@ +# ============================================================ +# ZCLAW SaaS Backend - Environment Variables +# ============================================================ +# Usage: +# cp saas-env.example .env +# # Edit .env with your actual values +# docker compose up -d +# ============================================================ + +# ---- PostgreSQL 配置 ---- +POSTGRES_USER=zclaw +POSTGRES_PASSWORD=请修改为强密码 +POSTGRES_DB=zclaw_saas + +# ---- SaaS 后端配置 ---- + +# 数据库连接 URL (Docker 内部网络使用主机名 postgres) +ZCLAW_DATABASE_URL=postgres://zclaw:请修改为强密码@postgres:5432/zclaw_saas + +# JWT 签名密钥 (至少32字符随机字符串) +# 生成命令: openssl rand -hex 32 +ZCLAW_SAAS_JWT_SECRET=请使用openssl_rand_hex_32生成 + +# TOTP/API Key 加密密钥 (64字符hex) +# 生成命令: openssl rand -hex 32 +ZCLAW_TOTP_ENCRYPTION_KEY=请使用openssl_rand_hex_32生成 + +# ---- 初始管理员账号 ---- +ZCLAW_ADMIN_USERNAME=admin +ZCLAW_ADMIN_PASSWORD=请修改为强密码 + +# ---- 运行模式 ---- +# 开发模式 (生产环境必须为 false 或不设置) +# 设置为 true 会放宽安全限制: Cookie Secure=false, CORS 宽松等 +ZCLAW_SAAS_DEV=false