docs: add production deployment plan

This commit is contained in:
kdletters
2026-05-02 02:58:14 +08:00
parent fb6fb6e9f5
commit 879a53bf8d

316
生产部署计划.md Normal file
View File

@@ -0,0 +1,316 @@
# 生产部署计划
更新时间2026-05-02
## 目标
将当前部署方式调整为单机生产推荐方案:生产运行路径不使用 Docker不再使用旧的一体化启动脚本由 systemd 托管 SpacetimeDB 与 Rust `api-server`,由 Nginx 托管主站、后台前端与必要反向代理。
本计划用于重新创建 Jenkins 流水线、服务器环境配置、网站发布、`api-server` 发布、SpacetimeDB 模块发布,以及数据库人工导入导出流程。
## 生产架构
- Nginx 作为唯一公网入口,负责 HTTPS、静态站点、后台静态页面、维护页与 `/admin/api/` 反向代理。
- SpacetimeDB 作为系统服务运行,监听 `127.0.0.1:3000`,数据根目录为 `/stdb`
- Rust `api-server` 作为系统服务运行,监听 `127.0.0.1:8082`,只被 Nginx 的 `/admin/api/` 访问。
- 主站与后台前端构建为静态文件,发布到服务器固定目录,不放入 Jenkins 目录,也不跟随 Docker 镜像。
- 除网站静态发布外,`api-server` 发布、SpacetimeDB 模块发布、数据库导入、服务器配置变更都必须先进入维护模式。
## 服务器目录
- `/opt/genarrative/releases/<version>/`:每次发布的完整版本目录。
- `/opt/genarrative/current`:指向当前生效版本的软链接。
- `/srv/genarrative/web`:指向 `/opt/genarrative/current/web`,供 Nginx 托管静态站点。
- `/etc/genarrative/api-server.env``api-server` 生产环境变量文件。
- `/var/lib/genarrative/maintenance/enabled`:维护模式开关文件。
- `/stdb`SpacetimeDB 程序、配置与数据根目录。
## 生产密钥
`/etc/genarrative/api-server.env` 中的生产密钥指所有只能存在于生产服务器、不能进入 Git、不能进入构建产物的敏感配置。典型内容包括
- LLM 或第三方服务 API Key。
- 短信服务 Access Key 与 Secret。
- 后台登录、会话、签名、加密相关密钥。
- 生产 SpacetimeDB 地址与数据库名。
- 只允许生产使用的回调地址、白名单或内部令牌。
该文件由服务器配置流水线或人工初始化创建,权限建议为 `root:genarrative``0640`。Jenkins 构建任务不能读取该文件;只有生产发布或服务启动需要读取。
## systemd 服务
### SpacetimeDB
- 服务名:`spacetimedb.service`
- 运行用户:`spacetimedb`
- 工作目录:`/stdb`
- 启动命令:`/stdb/spacetime --root-dir=/stdb start --listen-addr=127.0.0.1:3000`
- 对外暴露:默认不直接暴露公网端口。
该方案与 SpacetimeDB 官方自托管文档一致:使用 Ubuntu、专用用户、`/stdb` 根目录、systemd 服务和 Nginx。
### api-server
- 服务名:`genarrative-api.service`
- 运行用户:`genarrative`
- 工作目录:`/opt/genarrative/current`
- 可执行文件:`/opt/genarrative/current/api-server`
- 环境文件:`/etc/genarrative/api-server.env`
- 监听地址:`127.0.0.1:8082`
`api-server` 不放入 Docker也不直接暴露公网端口。发布时替换版本目录并重启 `genarrative-api.service`
## Nginx 规则
只保留必要入口:
- `/`:主站静态页面。
- `/admin/`:后台前端静态页面,后台构建时使用 `/admin/` 作为 base path。
- `/admin/api/`:反向代理到 `http://127.0.0.1:8082/admin/api/`
- HTTP 到 HTTPS只保留 301 重定向。
- `/maintenance.html`:维护中页面。
移除这些公网反向代理:
- `/api/*`
- `/generated-*`
- 公网 `/healthz`
- 其他旧的一体化 web server 代理入口。
SpacetimeDB 公网路由默认保持收敛,只按实际前端 SDK 需要暴露最小集合。禁止开放可远程发布数据库或管理实例的通用入口。
## 维护模式
维护模式由 `/var/lib/genarrative/maintenance/enabled` 控制:
- 文件存在:进入维护模式。
- 文件不存在:退出维护模式。
行为:
- 网站静态资源发布不进入维护模式。
- `api-server` 发布、SpacetimeDB 模块发布、数据库导入、服务器配置变更必须进入维护模式。
- 普通页面在维护模式下展示 `/maintenance.html`
- `/admin/api/*` 在维护模式下返回 503。
- 静态资源仍允许访问,避免维护页样式和资源加载失败。
- 发布成功后自动解除维护模式。
- 发布失败时保持维护模式,并通过邮件通知人工处理。
## 构建产物
每次构建产物按版本号归档:
```text
build/<version>/
├─ web/
│ ├─ index.html
│ ├─ assets/
│ ├─ maintenance.html
│ └─ admin/
├─ api-server
├─ spacetime_module.wasm
├─ scripts/
│ ├─ spacetime-publish-prod.sh
│ ├─ database-export.sh
│ ├─ database-import.sh
│ ├─ maintenance-on.sh
│ ├─ maintenance-off.sh
│ └─ maintenance-status.sh
├─ deploy/
│ ├─ systemd/
│ │ ├─ spacetimedb.service
│ │ └─ genarrative-api.service
│ ├─ nginx/
│ │ ├─ genarrative.conf
│ │ └─ snippets/maintenance.conf
│ └─ env/api-server.env.example
└─ README.md
```
不再生成旧产物:
- `web-server.mjs`
- 旧的一体化 `start.sh`
- 旧的一体化 `stop.sh`
## Jenkins 节点
Jenkins 可运行在 Windows 或其他机器上,但构建与发布动作使用 Linux agent。
### 开发/构建实例
- 节点名:`genarrative-dev`
- 标签:`genarrative-linux dev build`
- 用途:拉代码、安装依赖、构建主站、构建后台、构建 `api-server`、构建 SpacetimeDB wasm、归档产物。
### 生产/发布实例
- 节点名:`genarrative-prod`
- 标签:`genarrative-linux prod deploy`
- 用途:服务器配置、发布静态网站、发布 `api-server`、发布 SpacetimeDB 模块、数据库导入导出、维护模式切换。
### SSH PEM 凭证
在 Jenkins 中使用 `SSH Username with private key` 类型添加 PEM 私钥:
- `genarrative-dev-ssh-key`:开发/构建实例 SSH 凭证。
- `genarrative-prod-ssh-key`:生产/发布实例 SSH 凭证。
推荐使用非 root 用户,例如 `jenkins`。该用户只通过 sudoers 获得必要命令权限,例如 `systemctl restart genarrative-api``nginx -t`、维护脚本、发布目录切换等。
## Jenkins 流水线
计划重新创建以下流水线:
1. `Genarrative-Server-Provision`
2. `Genarrative-Web-Build`
3. `Genarrative-Web-Deploy`
4. `Genarrative-Api-Build`
5. `Genarrative-Api-Deploy`
6. `Genarrative-Stdb-Module-Build`
7. `Genarrative-Stdb-Module-Publish`
8. `Genarrative-Database-Export`
9. `Genarrative-Database-Import`
10. `Genarrative-Full-Build-And-Deploy`
构建流水线运行在 `build && dev`,发布、导入导出和服务器配置流水线运行在 `deploy && prod`
构建流水线支持参数 `PUBLISH_AFTER_BUILD`
- `false`:只构建并归档产物。
- `true`:构建成功后触发对应发布流水线。
发布流水线必须从归档产物获取文件,不依赖构建 workspace 的本地状态。
## 流水线职责
### Genarrative-Server-Provision
用于生产服务器一次性或低频配置:
- 创建 `spacetimedb``genarrative` 等系统用户。
- 创建 `/stdb``/opt/genarrative``/srv/genarrative``/etc/genarrative``/var/lib/genarrative/maintenance`
- 安装或更新 SpacetimeDB。
- 安装 systemd unit。
- 安装 Nginx 配置和维护模式 snippet。
- 执行 `nginx -t`
- 启用并启动 `spacetimedb.service``genarrative-api.service`
该流水线属于高风险操作,默认要求人工确认后执行。
### Web Build / Deploy
构建:
- 构建主站静态文件。
- 构建后台前端base path 为 `/admin/`
- 生成或复制 `maintenance.html`
- 归档 `web/` 产物。
发布:
- 解包到 `/opt/genarrative/releases/<version>/web`
- 更新 `/opt/genarrative/current``/srv/genarrative/web` 指向。
- 执行 Nginx 配置测试和静态页面 smoke test。
- 不进入维护模式。
### Api Build / Deploy
构建:
- 编译 Rust `api-server`
- 归档单一可执行文件和必要运行说明。
发布:
- 进入维护模式。
- 解包到 `/opt/genarrative/releases/<version>/api-server`
- 更新 `/opt/genarrative/current`
- 重启 `genarrative-api.service`
- 检查本机 `/healthz`
- 成功后解除维护模式。
- 失败时保留维护模式并发邮件。
### Stdb Module Build / Publish
构建:
- 使用 `spacetime build` 构建 `spacetime_module.wasm`
- 归档 wasm 与发布脚本。
发布:
- 进入维护模式。
- 将 wasm 上传到生产实例。
- 在生产实例本机执行 `spacetime publish -s local --bin-path spacetime_module.wasm <database-name>`
- 成功后执行必要 smoke test。
- 成功后解除维护模式。
- 失败时保留维护模式并发邮件。
## 数据库导出与导入
### 导出
`Genarrative-Database-Export` 用于人工导出生产数据:
- 运行在 `deploy && prod`
- 进入维护模式,避免导出期间继续写入。
- 从本机 SpacetimeDB 导出指定数据库数据。
- 产物归档到 Jenkins并可额外保存到服务器备份目录。
- 成功后解除维护模式。
- 失败时保留维护模式并邮件通知。
### 导入
`Genarrative-Database-Import` 用于人工导入或恢复数据:
- 运行在 `deploy && prod`
- 必须要求人工确认目标数据库、导入文件和是否覆盖。
- 进入维护模式。
- 导入前先生成一次安全备份。
- 执行导入。
- 执行数据校验和服务 smoke test。
- 成功后解除维护模式。
- 失败时保留维护模式并邮件通知。
数据库表结构变更必须同步检查并更新 `migration.rs`,不能只发布 wasm。
## 全量构建并发布
`Genarrative-Full-Build-And-Deploy` 顺序:
1. 触发 `Genarrative-Web-Build`
2. 触发 `Genarrative-Api-Build`
3. 触发 `Genarrative-Stdb-Module-Build`
4. 触发 `Genarrative-Stdb-Module-Publish`
5. 触发 `Genarrative-Api-Deploy`
6. 触发 `Genarrative-Web-Deploy`
7. 执行生产 smoke test。
网站最后发布,避免后台或主站提前指向尚未完成发布的后端能力。
## 回滚
- 网站回滚:将 `/srv/genarrative/web``/opt/genarrative/current` 切回上一版本并 reload Nginx。
- `api-server` 回滚:将 `/opt/genarrative/current` 切回上一版本并重启 `genarrative-api.service`
- SpacetimeDB 模块回滚:发布上一版本 `spacetime_module.wasm`
- 数据回滚:使用导入流水线恢复指定备份,必须进入维护模式。
## 待落地文件
后续工程落地时需要新增或改造:
- `deploy/systemd/spacetimedb.service`
- `deploy/systemd/genarrative-api.service`
- `deploy/nginx/genarrative.conf`
- `deploy/nginx/snippets/maintenance.conf`
- `deploy/env/api-server.env.example`
- `scripts/deploy/maintenance-on.sh`
- `scripts/deploy/maintenance-off.sh`
- `scripts/deploy/maintenance-status.sh`
- 新 Jenkinsfile 或 Job DSL用于上述 10 条流水线。
- 更新旧部署文档,标记旧一体化脚本为废弃或迁移对象。
## 参考
- SpacetimeDB 官方自托管文档https://spacetimedb.com/docs/how-to/deploy/self-hosting/