6.3 KiB
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.x,apt-mark hold |
| Corepack | 0.34.6 |
Node 全局工具 |
| pnpm | 10.33.0 |
全局固定版本;项目应再用 packageManager 固定 |
| Nginx | 1.24.0-2ubuntu7.12 |
Ubuntu 24.04 security/updates,apt-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.local、yanzi、100.90.90.91 和 127.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;这不会关闭证书链、主机名或签名校验。
迁移阿里云后必须替换为正式域名证书,并完成:
- 把证书和私钥放入受控 Secret 路径。
- 更新
lisglosips-tls.conf。 - 将 HSTS 从开发值
300调整为生产值,建议先观察再提升至31536000。 - 验证自动续期、续期失败告警和回滚证书。
- 开放 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 -t、systemctl daemon-reload,再重启对应服务。卸载 Nginx或解除包固定不是常规回滚动作,只有确认恢复目标需要时才执行。
9. 已知事项
- NodeSource 仓库在本地代理链路上偶尔出现 TLS 握手中断;现有索引和已安装包可用。升级前必须先确认仓库恢复并校验候选版本。
- 当前证书仅供开发,不能用于阿里云生产。
- 80 已监听但被 nftables 拒绝;生产是否开放取决于证书签发方案。
- 当前 API 是 S05 无依赖占位服务,S07 后端骨架完成后替换。