文档/ 运维

安全与上生产

正式用起来之前,把这一页从头到尾走一遍。多数事故来自两件事:密钥没备份,或者服务被暴露到了公网。

两把密钥§

GPT-Load 有两把用途完全不同的密钥,别混淆:

密钥作用丢了会怎样
AUTH_KEY登录管理台换一把即可,不影响数据
ENCRYPTION_KEY加密存储的上游凭据已加密的凭据永久无法恢复

两把都可以在 .env 里显式指定;不指定时, 首次启动会自动生成并存放在数据目录下的 auth.key 与 encryption.key。

不支持主密钥轮换

本版本没有提供更换 ENCRYPTION_KEY 的能力。 一旦更换或丢失,已经存进去的渠道凭据就解不开了,只能全部重新录入。 换句话说:这把密钥要和数据库同等对待。

备份§

数据库和加密密钥必须成套备份。自动生成的 auth.key 与 encryption.key 在数据目录中; 显式设置的 AUTH_KEY 与 ENCRYPTION_KEY 则要从原来的 环境变量或密钥管理服务单独备份。

Compose 必须停机备份

SQLite 使用 WAL,不能在服务运行时直接打包数据卷。 Compose 的实际卷名还会随项目名变化,不能硬编码成 gpt-load-data。 请使用 数据库与备份 中的完整命令。

备份文件本身包含可解密的凭据, 要按敏感数据对待——加密存放,不要丢进公开的网盘或仓库。

换数据库驱动、迁移服务器时的注意事项见 数据库与备份。

网络边界§

服务默认只监听 127.0.0.1,也就是只有本机能访问。 这是有意的默认值——管理台一旦暴露到公网, 拿到 AUTH_KEY 就等于拿到了你所有的上游凭据。

不要图省事直接开放

把 HOST 改成 0.0.0.0 并把端口直接映射到公网 IP, 是最常见也最危险的做法。正确方式是通过反向代理,并加上 TLS 与访问控制。

需要远程访问时,按风险从低到高:

  1. SSH 端口转发——最安全,不需要改任何服务配置:
把远程服务映射到本机
ssh -L 3001:127.0.0.1:3001 user@your-server
# 然后在本机浏览器打开 http://127.0.0.1:3001
  1. 内网 / VPN——只在受控网络内暴露
  2. 反向代理 + TLS + 访问控制——确实需要公网访问时,见下一节

反向代理§

用 Nginx、Caddy 一类在前面挡一层,至少要做到三件事:启用 HTTPS、限制来源、不要把管理台和数据面一起裸奔。

Nginx 示例:管理面限制来源
server {
    listen 443 ssl;
    server_name gateway.example.com;

    # 证书配置略

    # 管理面:只允许可信来源
    location /api/ {
        allow 203.0.113.0/24;
        deny all;
        proxy_pass http://127.0.0.1:3001;
    }

    # 数据面:按需开放,注意流式响应要关缓冲
    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_buffering off;
        proxy_read_timeout 600s;
    }
}

proxy_buffering off 和较长的读超时是必要的—— 流式响应如果被代理缓冲住,客户端会一直等不到输出。

默认客户端 IP 是连接来源。反向代理后需要真实 IP 时,配置 CLIENT_IP_HEADER 并将 TRUSTED_PROXIES 限定为实际代理的 IP/CIDR,修改后重启;不要直接信任客户端传入的头。此地址统一用于日志、IP 限制和安全事件。

指定可信代理列表后,X-Forwarded-For 从右向左跳过可信代理,取首个不可信地址;全部可信时取最左侧。请求头缺失或无效时回退连接地址。TRUSTED_PROXIES 留空会直接信任选定请求头(X-Forwarded-For 取最左侧),只适用于入口代理保证覆盖或清理该头的环境。

文件权限§

受管的数据目录会被收紧到与运行身份相匹配的访问权限, 程序启动时自动处理,通常不需要你干预:

  • 数据目录:0700(仅属主可读写执行)
  • 数据库文件与两把密钥:0600(仅属主可读写)
  • Windows 前台运行使用当前用户 ACL;安装器服务使用服务 SID 与本地 Administrators ACL

如果无法确认目录归属或链接类型,程序会拒绝启动而不是降级运行——这是有意的,避免在权限不明的位置写入凭据。

不要泄漏的东西§

需要在业务请求外发前隐藏敏感文本,或按规则判断是否允许转发,可以配置下面两项功能。它们不替代本页的访问控制与备份要求。

  • 两把密钥——不要提交到仓库、贴进 issue、发在群里
  • 备份文件——它包含可解密的凭据
  • 截图——管理台截图里常带账号邮箱和密钥后缀, 发出去之前先打码
  • 访问密钥——虽然可以吊销,但泄漏期间的用量是真金白银

发现安全问题请按仓库 SECURITY.md 里的流程私下反馈,不要开公开 issue。

原始请求体记录默认关闭。开启后保存的是请求脱敏之前的客户端内容,可能含个人信息、密码、密钥或商业机密;请求脱敏规则不会保护这份记录。管理员及相应访问密钥持有者可查看,数据库和备份也需按敏感内容保护。只在获得记录权限并告知使用者后开启,用完关闭;已有记录仍按日志保留期清理。

上生产清单§

逐条确认,再让真实流量进来:

  • 密钥——AUTH_KEY 与 ENCRYPTION_KEY 已显式设置或已确认自动生成的值被备份
  • 备份——数据库和 encryption.key 一起备过,并且验证过能恢复
  • 网络——没有把服务直接绑到 0.0.0.0 暴露公网; 远程访问走 SSH 转发、内网或带 TLS 的反向代理
  • 管理面——/api 有来源限制,没有对公网开放
  • 访问密钥——按应用分别发放,设置了合理的限流与成本上限
  • 监控——知道去哪看健康状态与请求日志,见 监控与排障
  • 边界认知——理解成本是估算、2.0 面向单实例部署
单实例设计

2.0 只保证单个应用实例的正确性,实例之间不共享状态。 不要在多个实例前面挂负载均衡——调度、冷却、限流的状态都会各算各的。 需要更大规模时,按业务维度拆成多个独立部署。

查看完整的 2.0 已知限制 →

安全与上生产 - GPT-Load