Files
Genarrative/生产部署计划.md
2026-05-02 02:58:14 +08:00

317 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 生产部署计划
更新时间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/