2026-05-10 13:12:44 +08:00

4.9 KiB

光湖自部署密钥管理页 · secrets-vault

主权: TCS-0002∞ · ICE-GL∞ · 国作登字-2026-A-00037559 守护: 铸渊 · ICE-GL-ZY001 棒次: PR-5 (baton-005) 模板版本: 0.1.0

这是什么

光湖国内域名机 (ZY-SVR-CN01 / 广州 2C2G / guanghulab.com) 上的"自部署密钥管理页"。

1 步保存立即生效 —— vs GitHub Secrets 的 5 步 round-trip (登录 → 仓库 Settings → Secrets → New → Save → 再去 Actions → Re-run)。

为什么独立建:

场景 GitHub Secrets 自部署 vault
AutoDL 重开机后端口漂移 5 步, 还要重跑工作流 1 步保存, 立即生效
主密钥可见性 GitHub 看得见 主密钥落 .master, 仅本机 root 可读
域名机离线 没法改 没法改 (但本来就是给这台机器用的)
谁能进 全 repo collaborator 仅 SSH 隧道 + basic-auth

三层安全

  1. 网络层 —— Express 监听 127.0.0.1:8080, 永不 bind 公网
  2. nginx 层 —— /admin/ location allow 127.0.0.1; deny all; + basic-auth
  3. 加密层 —— vault.enc 走 AES-256-GCM, 主密钥 .master chmod 600

冰朔访问方式:

# 本地起隧道
ssh -L 8080:127.0.0.1:80 ubuntu@<2C2G_HOST>
# 浏览器访问
open http://localhost:8080/admin/
# 输入 basic-auth 用户名密码 (来自 _logs/vault-credentials-FIRST-BOOT.txt, 抄完删)

路由

公开 (走 nginx /admin/ + basic-auth)

方法 路径 作用
GET /admin/__healthz 健康检查
GET /admin/ 前端 SPA
GET /admin/secrets/ 列出已配置 key (遮罩值)
GET /admin/secrets/manifest 按工作流分组的元数据
POST /admin/secrets/:key 写入 {value}
DELETE /admin/secrets/:key 删除
POST /admin/secrets/autodl/save_and_refresh AutoDL 一键 (vault 落 + 探活 + 写 endpoint + pm2 reload)

内部 (本机 only · 神笔马良用)

方法 路径 作用
GET /internal/fetch/:key 拉明文 (仅 127.0.0.1)

文件布局

server/secrets-vault/
├── server.js                Express 入口
├── ecosystem.config.js      pm2 (max_memory_restart=128M)
├── package.json
├── lib/
│   ├── vault.js             AES-256-GCM 加解密 + 主密钥
│   ├── manifest.js          按 secrets-manifest.json 分组
│   └── refresh-inference.js AutoDL 探活+写 inference-endpoint.json
├── routes/
│   ├── secrets.js           /admin/secrets/* 路由
│   └── internal.js          /internal/fetch/* (本机 only)
└── tests/
    ├── vault.test.js        加解密 + 主密钥 + 篡改检测
    └── routes.test.js       路由烟测

落盘文件

文件 路径 权限 说明
主密钥 /data/guanghulab/secrets-vault/.master 600 32 字节随机, 首次启动生成
加密库 /data/guanghulab/secrets-vault/vault.enc 600 AES-256-GCM 加密的 JSON
basic-auth /etc/nginx/.htpasswd_admin 644 bootstrap 写入
首启凭据 /data/guanghulab/_logs/vault-credentials-FIRST-BOOT.txt 600 首启随机 user/pass, 抄完删

跑测试

cd server/secrets-vault
npm install
npm test

预期输出:

✔ loadOrCreateMaster 首次随机生成 32 字节 + chmod 600
✔ loadOrCreateMaster 重启加载已有 .master, 不重建
✔ set/get/delete/list — 加密落盘往返一致
✔ 加密文件不含明文 (基础保密线)
✔ 换主密钥后解密失败 (cc-004 防换机器忘 .master)
✔ vault.enc 篡改 (改 ciphertext) 应被 GCM tag 检测
✔ set 拒绝非字符串 value
✔ maskValue 长短分级遮罩
✔ GET /admin/__healthz 返回 vault 状态
✔ GET /admin/secrets/manifest 按 workflow 分组
✔ POST /admin/secrets/:key — 白名单外拒绝
✔ POST /admin/secrets/:key — key 名格式错拒绝
✔ POST /admin/secrets/:key — 强校验长度不够拒绝
✔ POST + GET + DELETE 完整往返 (值不返回明文, 只遮罩)
✔ /internal/fetch/:key 只允许本机 (loopback 通)
✔ /internal/fetch/:key — 未配置 key 返回 404
✔ autodl/save_and_refresh — host/port 缺失 → 400
✔ autodl/save_and_refresh — 探活失败仍然把 vault 落了 (vault_saved=true)

灾备 / 换机

主密钥 .master 不上 git, 不上 COS, 不传冰朔。换机器流程:

# 老机器
sudo cat /data/guanghulab/secrets-vault/.master | base64 > /tmp/master.b64
# 安全通道传到新机器 (例如 ssh 直传)
# 新机器
sudo bash -c 'base64 -d /tmp/master.b64 > /data/guanghulab/secrets-vault/.master && chmod 600 /data/guanghulab/secrets-vault/.master'
# 然后再 rsync vault.enc 过来

如果 .master 真的丢了,没办法恢复 — 重新生成 + 让冰朔在新页面里逐项重填一次 (大约 10 项, 5 分钟内搞定)。这是 cc-004 系统自管的代价:宁愿忘了重填,也不让密钥本身被外部托管。