Skip to content

07 · 公网试用上线 — 安全加固清单 ​

面向"把站开放给群里的人试用"这个场景。目标:别人能来试,但薅不到你的模型额度、也难以攻击你的服务器。

核心策略:只给账号,不给模型——服务器不配任何 LLM key,用户注册后在设置页填自己的 key,烧的是他自己的额度。你零成本、零额度风险。

引流走 QQ 群(见 README):试用地址 + 邀请码只在群内私发,公开文档不放服务器地址。本清单里的域名/IP 一律用占位符。


一、上线前必做(P0) ​

1. .env 配置 ​

bash
# —— 强制自配模型:三家 key 全部留空 ——
# 留空后,用户没配自己的 key 调生成会得到 400「请到模型设置页配置」,
# 绝不会回落到你的 key(见 app/llm/factory.py:resolve_provider_config)。
DEEPSEEK_API_KEY=
OPENAI_API_KEY=
GEMINI_API_KEY=

# —— 认证硬化 ——
APP_ENV=prod                       # 弱 JWT 密钥即拒启动(app/main.py)
JWT_SECRET=<64位随机串>            # 见下方生成命令;⚠️ 一旦上线别再改(见第三节)
ADMIN_PASSWORD=<强密码>            # 不改的话默认是 admin/admin12345,等于没锁
INVITE_CODE=<试用邀请码>          # 或走多邀请码体系(后台管理,可设次数上限)

生成随机密钥:

bash
python -c "import secrets; print(secrets.token_urlsafe(48))"

2. 确认 admin 已改密 ​

初始 admin 由启动迁移用 ADMIN_PASSWORD 创建。若你之前用默认密码起过服务,库里已有 admin/admin12345,改 .env 不会自动改旧密码——需登录后在后台改,或用新库。上线前务必确认 admin 不是默认密码。

3. 反向代理 + HTTPS + 防火墙 ​

  • 用 Caddy / Nginx 反代到容器的 8000 端口,配好 TLS(Caddy 自动签证书)。
  • 防火墙只放 443(和限制来源 IP 的 22);关掉 8080/8000 的公网直连,别让人绕过反代直接打容器。
  • 反代要设置可信的 X-Forwarded-For,限流才能按真实 IP 生效(见下)。

Caddy 示例:

your-domain.com {
    reverse_proxy 127.0.0.1:8000
}

4. 试用邀请码设次数上限 ​

后台「邀请码管理」新建试用码时设 max_uses(如 50),用完自动失效——放量可控,不怕邀请码泄露后被无限刷号。


二、代码已内置的加固(无需额外操作) ​

能力说明位置
登录/注册限流按 IP:登录 20 次/5min、注册 10 次/1h,超限 429app/ratelimit.py
per-user key 加密存储用户 key 用 Fernet 加密后落库,防 DB 文件泄露连带泄 keyapp/crypto.py
base_url SSRF 校验保存配置时拒绝把 base_url 指向内网/本机/云元数据app/net_guard.py
弱 JWT 密钥 fail-fastAPP_ENV=prod 下用默认密钥即拒启动app/main.py
数据隔离项目/任务按 user 隔离,越权按 404 处理app/auth.py
密码 bcrypt 哈希不存明文app/auth.py

三、运维注意 ​

  • 别改已上线的 JWT_SECRET:key 加密的密钥从它派生,改了会导致①所有人 token 失效(需重登)②已存的模型 key 无法解密,用户得在设置页重填。真要轮换就提前通知。
  • 多 worker 会削弱限流:当前 Dockerfile 是单进程 uvicorn,内存限流准确。若日后加 --workers 或上 gunicorn,各进程计数独立,需换成 Redis 等共享存储。
  • 定期备份 SQLite:jarvis_write_data 卷里的 *.db;备份文件同样含(已加密的)用户 key,注意存放权限。
  • 看谁在用:后台用户列表带用量汇总(llm_usage 表按 user 记账),能看出异常账号。

四、后续可选(P2) ​

  • fail2ban / WAF 挡暴力与扫描。
  • DNS rebinding 防护:SSRF 校验目前在"保存配置"时做,理论上可被解析时公网、请求时内网绕过;高价值场景可在发请求时再校验一次。
  • 用户 key 加密密钥独立于 JWT_SECRET(单独 ENC_KEY),解耦"轮换登录密钥"和"重填模型 key"。

基于 Apache License 2.0 开源