Skip to content

启动、配置与事实来源

这一页解决一个很容易混淆的问题:改了环境变量、管理后台或数据库后,Sub2API 到底会听谁的,以及改动什么时候生效。

先记住三个结论:

  1. ADMIN_EMAILADMIN_PASSWORD 只用于首次创建管理员,不是持续覆盖数据库的登录配置。
  2. PostgreSQL 是用户、账号、分组、订单和后台设置等业务数据的事实来源。
  3. YAML/环境变量主要控制进程启动和基础设施;Redis 与进程内存保存缓存、锁、并发和临时状态。

启动状态机

入口位于 backend/cmd/server/main.go,启动路径不是始终相同:

text
server --version ───────────────▶ 输出版本后退出
server --setup ─────────────────▶ CLI 设置向导
普通启动
  ├─ NeedsSetup = true
  │    ├─ AUTO_SETUP=true ──────▶ 从环境变量自动安装 ─▶ 正常服务
  │    └─ AUTO_SETUP=false ─────▶ Web 设置服务 ──────▶ 安装后重启
  └─ NeedsSetup = false ────────▶ 加载完整配置 ──────▶ 正常服务

NeedsSetup() 只检查数据目录中的两个本地文件:

  • config.yaml 是否存在。
  • .installed 安装锁是否存在。

只要其中任意一个存在,系统就不会重新进入初始化。它不会仅凭“数据库里已有用户”判断已安装。

这意味着生产环境必须持久化 DATA_DIR。如果应用数据卷丢失,但仍连接原来的 PostgreSQL,实例会重新走安装流程;代码会因为数据库已有用户而跳过管理员创建,但仍可能重写本地配置。固定的 JWT_SECRET 也必须由部署系统保存,不能依赖每次自动生成。

Auto Setup 实际做什么

AUTO_SETUP=true 时,backend/internal/setup/setup.go 会依次:

  1. 从环境变量组装 PostgreSQL、Redis、管理员、Server、JWT 和时区配置。
  2. 测试 PostgreSQL;目标数据库不存在时尝试创建。
  3. 测试 Redis。
  4. 执行数据库迁移。
  5. 判断是否需要创建管理员。
  6. 写入权限为 0600config.yaml
  7. 写入权限为 0400.installed
  8. 继续启动正式服务。

管理员创建还有额外保护:

数据库状态结果
没有任何用户,也没有管理员创建 ADMIN_EMAIL 对应的管理员
已有管理员跳过管理员初始化
已有普通用户但没有管理员为避免覆盖既有数据,仍跳过自动创建

ADMIN_PASSWORD 为空时,安装过程生成一次性随机密码并输出到启动日志。该密码不会再次显示。

为什么改 ADMIN_PASSWORD 不能重置密码

登录路径读取 users.password_hash,使用 bcrypt 校验用户提交的密码。初始化完成后:

text
ADMIN_PASSWORD 环境变量

        └─ 仅首次安装时参与 SetPassword()


          users.password_hash(PostgreSQL)


               后续每次登录

因此重启容器或修改平台变量不会更新现有管理员。正常方式是在后台修改密码或执行受控的数据库恢复操作。密码变更会改变 JWT 的 token version 指纹,使旧访问令牌失效。

排查登录时至少确认:

sql
SELECT id, email, role, status, deleted_at
FROM users
WHERE role = 'admin';

不要把环境变量里显示的明文当成当前登录密码,也不要把明文密码直接写入 password_hash

启动配置优先级

正常配置由 Viper 加载,优先级是:

text
环境变量
   ↓ 覆盖
config.yaml
   ↓ 覆盖
程序默认值

环境变量名由配置路径转成大写并用下划线连接,例如:

text
database.max_open_conns  → DATABASE_MAX_OPEN_CONNS
gateway.max_body_size    → GATEWAY_MAX_BODY_SIZE
jwt.secret               → JWT_SECRET

配置文件按以下目录查找:

  1. DATA_DIR 指定目录。
  2. /app/data
  3. 当前目录。
  4. ./config
  5. /etc/sub2api

这里的“环境变量覆盖 YAML”只针对同一个启动配置键。它不代表环境变量可以覆盖 PostgreSQL 中的用户、账号或订单。

五类状态分别归谁

状态类型事实来源示例丢失/修改后的行为
进程启动配置环境变量或 config.yamlDB 地址、Redis、JWT、连接池、超时多数需要重启进程
持久业务数据PostgreSQL 业务表用户、密码哈希、账号、分组、订单、用量页面和网关最终都以 DB 为准
动态系统设置PostgreSQL settings注册、支付、站点、OAuth、调度策略部分按请求读取,部分刷新本地缓存
分布式运行状态Redis并发、限流、粘性、刷新锁、队列通常有 TTL,可重建性因功能而异
单实例运行状态进程内存L1 缓存、HTTP/WS 连接池、worker 队列重启后丢失并重建

本地 data/ 还可能保存配置、定价文件、日志和自定义模板。它不是 PostgreSQL 的替代品,但仍属于备份范围。

管理后台设置怎样生效

管理后台的系统设置由 SettingService 写入 PostgreSQL,而不是反写 .env 或 YAML。更新成功后,服务会刷新若干当前进程缓存,并触发前端 HTML 配置缓存、CSP frame source 等本地回调。

不同设置的读取方式不同:

  • 一些功能在请求时直接读取 settings
  • 一些设置有 TTL 缓存或 singleflight。
  • 少数设置会同步更新当前进程的原子值。
  • 支付 Provider Registry、Web Search Manager 等对象需要显式重建。

所以不能笼统地说“后台保存后所有副本立刻生效”。单实例通常立即或在下一次读取生效;多实例必须确认该设置是否有共享失效机制、TTL 或重启要求。高风险支付、鉴权和调度设置变更后,应逐副本验证。

改哪里最合适

需求正确入口是否重启
修改数据库/Redis 地址部署环境变量或 YAML
修改 JWT/TOTP 加密密钥Secret 管理系统是,并评估历史数据/会话影响
修改管理员登录密码用户资料/管理员用户接口;紧急时受控 DB 恢复
添加上游 API KeyAccount 业务数据
修改站点名称、注册、支付开关管理后台 Settings通常否,但要验证多实例
修改连接池、请求体、网关超时环境变量或 YAML
清除账号限流/错误专用账号恢复接口
清空 Redis只用于明确的故障恢复会影响全局运行状态,不是普通配置动作

Secret 的生命周期

Secret保存位置轮换影响
JWT_SECRET启动配置现有访问/刷新会话失效;所有副本必须一致
TOTP_ENCRYPTION_KEY启动配置错误轮换会导致既有 TOTP secret 无法解密
PostgreSQL/Redis 密码部署 Secret需要协调服务端与应用滚动切换
上游 API Key/OAuth tokenPostgreSQL Account 凭证要失效 token/调度缓存并做真实请求测试
支付 Provider SecretPostgreSQL Provider 配置影响回调验签与历史订单查询
SMTP/OAuth Client SecretPostgreSQL Settings 或启动配置需要验证对应登录/邮件流程

Secret 不应出现在文档、工单、截图和普通日志中。轮换前先确认旧数据是否依赖该密钥解密,而不仅是验证新请求。

开发新配置项时

新增配置前先决定它属于哪类:

  • 启动配置:影响基础设施、连接池、协议底座,适合 config.Config
  • 动态业务设置:管理员需要在线修改,适合 settings + SettingService
  • 领域实体字段:只属于某个 Account/Group/User,放对应 schema。
  • 临时运行状态:需要 TTL、跨实例协调时放 Redis。

实现时同时补齐:默认值、校验、环境变量映射、后台 DTO、脱敏、缓存失效、多实例传播、测试和部署文档。不要让同一个键同时在 YAML 和 settings 中各自生效,却没有明确覆盖规则。

变更后的验证

  1. 在目标实例打印或通过安全的诊断接口确认最终配置,不打印 Secret。
  2. 验证 PostgreSQL 和 Redis 实际连接目标。
  3. 对后台设置检查数据库值以及每个副本的行为。
  4. 对认证变更重新登录,并验证旧 Token 是否按预期失效。
  5. 对上游凭证执行 Account Test 和真实 Group 请求。
  6. 对支付、计费或调度设置保留回滚值,并观察错误与审计日志。

部署参数全集见配置方式与关键参数,生产修改步骤见变更、升级、备份与恢复

本文档用于帮助你理解、部署和运维 Sub2API。使用前请确认上游服务条款与当地法律要求。