Files
lisglosips/docs/SERVER_B_WEB_RUNTIME_RUNBOOK.md

6.3 KiB
Raw Permalink Blame History

Server B Web 运行时 Runbook

本文记录 S05 在 Server B 上建立的 Node.js、pnpm、Nginx、systemd 与开发 TLS 基线。当前环境是本地 KVM 开发环境,不是阿里云生产环境。

1. 固定版本

组件 版本 管理方式
Node.js v22.22.2 / Debian 包 22.22.2-1nodesource1 NodeSource 22.xapt-mark hold
Corepack 0.34.6 Node 全局工具
pnpm 10.33.0 全局固定版本;项目应再用 packageManager 固定
Nginx 1.24.0-2ubuntu7.12 Ubuntu 24.04 security/updatesapt-mark hold

Node.js 22 当前属于 LTS 线。固定包在升级前必须先核对 Node/Nginx 安全公告、NestJS/Prisma 兼容性并完成回归测试。

版本记录:/etc/lisglosips/web-runtime-versions.env

2. 目录与发布模型

/opt/lisglosips/
├── releases/
│   └── s05-placeholder-20260620/
│       ├── public/index.html
│       └── server.mjs
└── current -> /opt/lisglosips/releases/s05-placeholder-20260620
  • 发布目录由 root:lisglosips 持有,程序只读。
  • current 必须是指向完整 release 的符号链接。
  • 正式发布先写入新 release,完成校验后再原子切换 current
  • 不允许直接在 current 指向的 release 内在线修改代码。
  • systemd 可写状态目录为 /var/lib/lisglosips,运行目录为 /run/lisglosips

3. systemd 服务模板

模板:/etc/systemd/system/lisglosips@.service

实例环境文件:/etc/lisglosips/<实例名>.env,权限必须为 0640 root:lisglosips。当前实例:

lisglosips@api.service -> /etc/lisglosips/api.env

模板默认使用 lisglosips 系统用户,启用只读系统、私有临时目录、空 capability、设备隔离和内核保护。后续 Worker 如需写录音目录,应使用实例 drop-in 精确增加 ReadWritePaths,不要放宽整个模板。

常用命令:

sudo systemctl status lisglosips@api
sudo systemctl restart lisglosips@api
sudo journalctl -u lisglosips@api -n 100 --no-pager
sudo systemd-analyze security lisglosips@api.service

4. Nginx 路由

路径 行为
/ /opt/lisglosips/current/public 静态站点,支持 SPA fallback
/healthz 反向代理到 127.0.0.1:3000
/api/ API 代理,单 IP 20 r/s、burst 40
/api/auth/login 登录专用限制,单 IP 5 r/min、burst 3
/_recordings/ 仅供 X-Accel-Redirect 内部访问,外部请求返回 404

关键文件:

/etc/nginx/conf.d/lisglosips-global.conf
/etc/nginx/sites-available/lisglosips.conf
/etc/nginx/snippets/lisglosips-proxy.conf
/etc/nginx/snippets/lisglosips-security-headers.conf
/etc/nginx/snippets/lisglosips-tls.conf

应用仅监听 127.0.0.1:3000。Nginx 监听 80/443,但 nftables 仅允许已登记管理端访问 443;开发阶段没有对外开放 80。

配置变更:

sudo nginx -t
sudo systemctl reload nginx

5. 开发 TLS

开发 CA 和证书位于:

/etc/lisglosips/pki/ca/lisglosips-dev-ca.crt
/etc/lisglosips/pki/ca/lisglosips-dev-ca.key
/etc/lisglosips/pki/certs/server.crt
/etc/lisglosips/pki/private/server.key

CA 私钥为 0600 root:root,服务器私钥为 0640 root:www-data。证书 SAN 包含 lisglosips.localyanzi100.90.90.91127.0.0.1

重新签发开发证书:

sudo /usr/local/sbin/lisglosips-issue-dev-cert
sudo nginx -t
sudo systemctl reload nginx

本机公有 CA 副本保存在 .codex-private/tls/lisglosips-dev-ca.crt,不得把 CA 私钥复制出 Server B。Windows 使用私有 CA 测试时,因开发 CA 不发布 CRL,curl 需附加 --ssl-no-revoke;这不会关闭证书链、主机名或签名校验。

迁移阿里云后必须替换为正式域名证书,并完成:

  1. 把证书和私钥放入受控 Secret 路径。
  2. 更新 lisglosips-tls.conf
  3. 将 HSTS 从开发值 300 调整为生产值,建议先观察再提升至 31536000
  4. 验证自动续期、续期失败告警和回滚证书。
  5. 开放 80 仅用于 ACME/跳转,或使用 DNS-01 后继续关闭 80。

6. 健康检查

curl --fail http://127.0.0.1:3000/healthz
curl --fail --cacert /etc/lisglosips/pki/ca/lisglosips-dev-ca.crt \
  https://127.0.0.1/healthz
sudo ss -lntp | grep -E ':(80|443|3000)\b'
sudo systemctl --failed

预期:

  • /healthz 返回 status=ok
  • 3000 仅出现在 127.0.0.1
  • 443 由 Nginx 监听。
  • 首页响应包含 HSTS、CSP、X-Frame-Options、X-Content-Type-Options 和 Permissions-Policy。
  • TLS 1.2/1.3 可用,TLS 1.1 被拒绝。

7. 新版本发布

release="2026xxxxTxxxxxxZ"
sudo install -d -o root -g lisglosips -m 0750 "/opt/lisglosips/releases/$release"
# 将已经构建和校验的产物放入新 release。
sudo chown -R root:lisglosips "/opt/lisglosips/releases/$release"
sudo find "/opt/lisglosips/releases/$release" -type d -exec chmod 0750 {} +
sudo find "/opt/lisglosips/releases/$release" -type f -exec chmod 0640 {} +
sudo ln -sfn "/opt/lisglosips/releases/$release" /opt/lisglosips/current
sudo systemctl restart lisglosips@api
sudo nginx -t && sudo systemctl reload nginx

发布后必须检查内部健康、HTTPS 健康、日志、应用端口监听和前端静态文件。数据库迁移从 S08 起必须在切换 current 前按迁移 Runbook 执行。

8. 回滚

应用回滚:把 current 指回上一 release,重启应用并检查 HTTPS 健康。

sudo ln -sfn /opt/lisglosips/releases/<previous> /opt/lisglosips/current
sudo systemctl restart lisglosips@api

S05 变更前备份:

/var/backups/lisglosips-s05/20260620T123432Z

其中 pre-change.tar.gz 包含变更前应用与配置,SHA256SUMS 用于恢复前校验。恢复 Nginx/systemd 配置后必须执行 nginx -tsystemctl daemon-reload,再重启对应服务。卸载 Nginx或解除包固定不是常规回滚动作,只有确认恢复目标需要时才执行。

9. 已知事项

  • NodeSource 仓库在本地代理链路上偶尔出现 TLS 握手中断;现有索引和已安装包可用。升级前必须先确认仓库恢复并校验候选版本。
  • 当前证书仅供开发,不能用于阿里云生产。
  • 80 已监听但被 nftables 拒绝;生产是否开放取决于证书签发方案。
  • 当前 API 是 S05 无依赖占位服务,S07 后端骨架完成后替换。