# 09 · 环境变量与密钥规范 | 项 | 内容 | | --- | --- | | 文档版本 | V1.0(2026-11-02) | | 依据 | 技术架构 附录 C(关键环境变量)、§2.8(安全)、§4.1 / §4.4 | | 适用范围 | 所有环境(dev / staging / prod)、CI、本地开发 | | 强制级别 | 强制 | --- ## 1 基本规则 - `ENV-01` 只有 `.env.example` 入库;`.env`、`.env.local`、`.env.*.local` 一律不入库(`.gitignore` 已覆盖)。 - `ENV-02` 变量名 `UPPER_SNAKE_CASE`,按前缀分组;新增变量必须同时更新 `.env.example`、本文附录、部署配置三处。 - `ENV-03` 应用启动时用 Zod 校验环境变量,**缺失或非法直接 fail fast**,禁止带默认值「悄悄跑起来」。 - `ENV-04` 代码中只能通过集中配置模块读取(`config/env.ts`),**禁止**到处 `process.env.XXX`。 - `ENV-05` 禁止在仓库、PR、聊天工具、日志中传递真实密钥;示例值用 `xxx` / `changeme`。 - `ENV-06` 三个环境密钥**完全独立**:dev / staging / prod 不得复用同一套数据库、Redis、S3、JWT、AI 密钥。 --- ## 2 变量清单(前缀分组) ### 运行与数据库 | 变量 | 说明 | 示例 | | --- | --- | --- | | `NODE_ENV` | 运行环境 | `development` / `production` | | `DATABASE_URL` | PG 连接串 | `postgresql://user:pass@host:5432/lingxi` | | `REDIS_URL` | Redis 连接串 | `redis://host:6379/0` | | `QUEUE` | worker 订阅队列名 | `image:render` | ### 对象存储(S3 协议) | 变量 | 说明 | | --- | --- | | `S3_ENDPOINT` | MinIO / 云 OSS 端点 | | `S3_ACCESS_KEY` / `S3_SECRET_KEY` | 访问密钥(按环境独立) | | `S3_BUCKET_ASSETS` / `S3_BUCKET_RENDERS` / `S3_BUCKET_TEMP` | 资产 / 产物 / 临时桶 | | `S3_BUCKET_ARCHIVE` / `S3_BUCKET_UPLOADS` / `S3_BUCKET_EXPORTS` | 归档 / 上传 / 导出桶 | ### 认证与安全 | 变量 | 说明 | | --- | --- | | `JWT_SECRET` / `JWT_REFRESH_SECRET` | 长度 ≥ 32,按环境独立 | | `ENCRYPTION_KEY` | AES-256-GCM 主密钥(加密 AI 供应商密钥等) | | `PUBLIC_LINK_HMAC_SECRET` | 免登录审核 / 分享链接签名密钥 | ### AI 接入 | 变量 | 说明 | | --- | --- | | `AI_PROVIDER__API_KEY` | 按供应商分(如 `AI_PROVIDER_JIMENG_API_KEY`) | | `AI_PROVIDER__BASE_URL` | 自定义端点(可选) | | `AI_ROUTE_REFRESH_MS` | 路由表缓存刷新间隔 | > 供应商 API Key 以加密形式存库(`ai_configs`)时,环境变量只用于**首次注入 / 灾备**;运行时读取库内配置,避免多处真相。 ### 媒体处理 | 变量 | 说明 | | --- | --- | | `FFMPEG_PATH` / `FFPROBE_PATH` | 二进制路径(镜像内固定) | | `MAX_UPLOAD_MB` | 单文件上限 | | `WORKER_CONCURRENCY` | 单 worker 并发 | ### 成本与开关 | 变量 | 说明 | | --- | --- | | `COST_SOFT_LIMIT` / `COST_HARD_LIMIT` | 预算软 / 硬限(默认 0.8 / 1.0) | | `FEATURE_VIDEO` | 视频线开关 | | `OTEL_EXPORTER_OTLP_ENDPOINT` | 链路追踪导出端点 | --- ## 3 密钥管理 | 项 | 规则 | | --- | --- | | 存储 | 生产用云 KMS / Vault / Secrets Manager;**禁止**明文写进 compose 或镜像 | | 注入 | CI/CD 注入环境变量;本地用 `.env.local`(不入库) | | 加密 | AI 供应商密钥等入库字段用 AES-256-GCM,密钥不落同一库 | | 权限 | 应用 DB 账号非 superuser;MinIO 按桶最小权限;CI 只读必要范围 | | 轮换 | JWT / HMAC / 加密密钥至少每 6 个月或人员变动时轮换;轮换需兼容期(新旧并存) | | 审计 | 密钥变更记审计(谁、何时、哪个 key 的版本号,**不记值**) | - `ENV-07` 前端只能暴露 `VITE_PUBLIC_*` 前缀变量;构建产物必须扫描确认无服务端密钥。 - `ENV-08` 禁止把密钥拼进 URL / query / 日志 / 异常信息。 - `ENV-09` 本地开发连的 MinIO / PG 凭据只能是 dev 值,且与生产不一致。 --- ## 4 泄露处置(30 分钟内) 1. **立即轮换**对应密钥(先轮换再排查,不等待确认)。 2. 撤销相关 token / session,作废签名链接。 3. 检查访问日志与 `ai_usage`,评估是否被滥用(尤其 AI 费用)。 4. 用 `git filter-repo` 清理历史并强制全员重新 clone(见 [01](01-Git规范.md) `GIT-20`)。 5. 24 小时内出复盘:泄露路径、影响面、改进项(通常补 CI 扫描 / pre-commit)。 - `ENV-10` 泄露事件必须记录在案,**禁止**「悄悄换掉当没发生」。 --- ## 5 本地开发 ```bash cp .env.example .env.local # 填 dev 值(不得填生产值) pnpm compose:up # PG 18 / Redis 7.4 / MinIO pnpm db:migrate && pnpm db:seed pnpm dev ``` - `ENV-11` 禁止 `docker compose down -v` 清库;重置数据用 `pnpm db:reset`。 - `ENV-12` 本地不得连生产数据库 / 生产对象存储 / 生产 AI 供应商(费用与数据风险)。 - `ENV-13` 开发机 Node 版本由 `.nvmrc` 固定,`package.json` 声明 `engines`,`preinstall` 用 `only-allow pnpm` 拦截其他包管理器。 --- ## 6 检查清单 - [ ] 新增变量已写 `.env.example` 与本文 - [ ] 启动校验覆盖新变量,缺失即失败 - [ ] 未在代码中散读 `process.env` - [ ] 三环境密钥独立,未复用 - [ ] 无密钥进日志 / URL / 前端 bundle - [ ] 生产密钥来自 KMS / Secrets Manager - [ ] 轮换与泄露处置流程已知晓