317 lines
11 KiB
Markdown
317 lines
11 KiB
Markdown
# 生产部署计划
|
||
|
||
更新时间: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/
|