forked from wangziqi/gongxue-base
feat: establish production SaaS foundation
This commit is contained in:
@@ -1,385 +1,470 @@
|
||||
# tiku-supabase 云服务器部署说明
|
||||
# SaaS 题库服务器部署手册
|
||||
|
||||
本文档用于把当前仓库部署到云服务器,并和已经解析好的域名打通。仓库内只保存安全模板,真实密钥、数据库密码、支付密钥、短信密钥、对象存储密钥和 Gitea 部署凭证必须放在服务器 `/etc/tiku-saas/` 下,不能提交到 Git。
|
||||
本手册覆盖两类场景:
|
||||
|
||||
## 域名规划
|
||||
1. 全新测试/预生产服务器的隔离 bootstrap。
|
||||
2. 现有云服务器从旧原地覆盖脚本升级到版本化原子发布。
|
||||
|
||||
建议先按下面 6 个域名落地:
|
||||
生产发布器默认 fail closed。缺少真实数据库 readiness、三端 runtime config、生产 evidence、浏览器烟测环境或服务重启权限时,发布必须失败,不能通过关闭门禁或伪造 evidence 绕过。
|
||||
|
||||
| 域名 | 用途 | 服务器转发 |
|
||||
| --- | --- | --- |
|
||||
| `api.tjszsb.com` | 自研业务 API,Taro/H5/小程序统一调用 | `127.0.0.1:8787` |
|
||||
| `app.tjszsb.com` | 学生 H5 题库端 | `/srv/tiku-saas/www/student` |
|
||||
| `admin.tjszsb.com` | 租户后台 H5 | `/srv/tiku-saas/www/tenant-admin` |
|
||||
| `console.tjszsb.com` | SaaS 平台后台 H5 | `/srv/tiku-saas/www/platform-admin` |
|
||||
| `supabase.tjszsb.com` | Supabase API gateway/Auth/Storage/PostgREST | Supabase gateway,通常是 `127.0.0.1:8000` |
|
||||
| `studio.tjszsb.com` | Supabase Studio 运维后台 | 仅允许固定 IP/VPN/内网访问 |
|
||||
## 先选择入口
|
||||
|
||||
`studio.tjszsb.com` 不建议裸露给公网。若必须临时开放,至少要加 Nginx IP 白名单、强密码、服务器防火墙和访问日志审计。
|
||||
| 场景 | 入口 | 配置模型 | 状态 |
|
||||
| --- | --- | --- | --- |
|
||||
| 全新生产服务器 | 仓库根目录 `deploy.sh` | `/opt/tiku-saas/shared/` | 推荐 |
|
||||
| 现有云服务器 | `scripts/deploy/bin/deploy.sh` 安装到 `/opt/tiku-saas/bin/deploy.sh` | `/etc/tiku-saas/` | 兼容升级入口 |
|
||||
| 全新测试/预生产服务器 | 本手册的 staging bootstrap | 完全独立目录、数据库、域名和凭据 | 当前无一键 staging profile |
|
||||
|
||||
## 服务器目录
|
||||
两套生产脚本的变量名不同,不能混用 env 模板:
|
||||
|
||||
推荐使用固定目录,方便后续脚本和 AI 协作不漂移:
|
||||
- 根脚本:`REPO_URL`、`BRANCH`、`DEPLOY_ROOT`,模板为根目录 `deploy.env.example`。
|
||||
- 兼容脚本:`GIT_REPO`、`GIT_BRANCH`、`APP_ROOT`,模板为 `scripts/deploy/env/deploy.env.example`。
|
||||
|
||||
```text
|
||||
/opt/tiku-saas/repo Git 工作副本
|
||||
/opt/tiku-saas/bin 服务器本地执行脚本
|
||||
/srv/tiku-saas/www/student 学生端 H5 静态文件
|
||||
/srv/tiku-saas/www/tenant-admin 租户后台 H5 静态文件
|
||||
/srv/tiku-saas/www/platform-admin 平台后台 H5 静态文件
|
||||
/srv/tiku-saas/data 运行期数据
|
||||
/srv/tiku-saas/backups 数据库和对象存储备份
|
||||
/etc/tiku-saas/deploy.env 部署脚本配置,含 Gitea 只读部署凭证
|
||||
/etc/tiku-saas/api.env API 生产环境变量
|
||||
/etc/tiku-saas/worker.env worker 生产环境变量
|
||||
/etc/tiku-saas/runtime-config/ 三套 H5 公开运行时配置
|
||||
```
|
||||
|
||||
建议创建独立低权限用户:
|
||||
|
||||
```bash
|
||||
sudo useradd --system --create-home --shell /bin/bash deploy
|
||||
sudo mkdir -p /opt/tiku-saas/bin /srv/tiku-saas/www/student /srv/tiku-saas/www/tenant-admin /srv/tiku-saas/www/platform-admin /srv/tiku-saas/data /srv/tiku-saas/backups /etc/tiku-saas/runtime-config
|
||||
sudo chown -R deploy:deploy /opt/tiku-saas /srv/tiku-saas
|
||||
sudo chmod 750 /etc/tiku-saas
|
||||
```
|
||||
|
||||
## 宝塔服务器实际落地记录
|
||||
|
||||
2026-07-01 首次上云使用的是 Alibaba Cloud Linux 3 + 宝塔面板环境。该服务器的 80/443 已由宝塔 Nginx 接管,主配置不在 `/etc/nginx`,而在:
|
||||
|
||||
```text
|
||||
/www/server/nginx/conf/nginx.conf
|
||||
/www/server/panel/vhost/nginx/*.conf
|
||||
```
|
||||
|
||||
因此在这类服务器上不要执行 `systemctl start nginx`、不要写 `/etc/nginx/sites-available`,也不要覆盖宝塔生成的站点配置。宝塔 Nginx 的测试和重载命令是:
|
||||
|
||||
```bash
|
||||
/www/server/nginx/sbin/nginx -t -c /www/server/nginx/conf/nginx.conf
|
||||
/www/server/nginx/sbin/nginx -s reload
|
||||
```
|
||||
|
||||
本次保留企业目录隔离方案:
|
||||
|
||||
```text
|
||||
/opt/tiku-saas/repo Gitea 工作副本
|
||||
/opt/tiku-saas/bin 服务器部署脚本
|
||||
/srv/tiku-saas/www H5 发布产物
|
||||
/srv/tiku-saas/data 运行数据
|
||||
/srv/tiku-saas/backups 备份
|
||||
/etc/tiku-saas 真实 env、Gitea token、运行时配置
|
||||
```
|
||||
|
||||
宝塔新增站点时会拦截 `/srv` 作为网站根目录。不要因此把密钥、仓库或运行数据搬进 `/www`。只为 H5 静态站点创建 `/www/wwwroot` 下的软链接:
|
||||
|
||||
```bash
|
||||
mkdir -p /www/wwwroot/tiku-saas
|
||||
ln -sfn /srv/tiku-saas/www/student /www/wwwroot/tiku-saas/student
|
||||
ln -sfn /srv/tiku-saas/www/tenant-admin /www/wwwroot/tiku-saas/tenant-admin
|
||||
ln -sfn /srv/tiku-saas/www/platform-admin /www/wwwroot/tiku-saas/platform-admin
|
||||
chown -h deploy:deploy /www/wwwroot/tiku-saas/student
|
||||
chown -h deploy:deploy /www/wwwroot/tiku-saas/tenant-admin
|
||||
chown -h deploy:deploy /www/wwwroot/tiku-saas/platform-admin
|
||||
```
|
||||
|
||||
宝塔面板中新增三个纯静态站点:
|
||||
|
||||
| 域名 | 宝塔根目录 |
|
||||
| --- | --- |
|
||||
| `app.tjszsb.com` | `/www/wwwroot/tiku-saas/student` |
|
||||
| `admin.tjszsb.com` | `/www/wwwroot/tiku-saas/tenant-admin` |
|
||||
| `console.tjszsb.com` | `/www/wwwroot/tiku-saas/platform-admin` |
|
||||
|
||||
每个站点需要保留 H5 history fallback,并禁止缓存公开运行时配置:
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location = /runtime-config.json {
|
||||
add_header Cache-Control "no-store" always;
|
||||
try_files $uri =404;
|
||||
}
|
||||
```
|
||||
|
||||
当前服务器已经验证过的基础环境:
|
||||
|
||||
```text
|
||||
Node.js: v20.20.2,系统级安装在 /usr/bin/node,deploy 用户可用
|
||||
npm: 10.8.2,deploy 用户可用
|
||||
Docker: 26.1.3
|
||||
Docker Compose: v2.27.0
|
||||
Nginx: 宝塔 /www/server/nginx/sbin/nginx,1.30.1
|
||||
```
|
||||
|
||||
不要使用 root 的 nvm Node 路径作为生产运行时。若 `deploy` 用户看不到 Node/NPM,应安装系统级 NodeSource Node.js 20:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
|
||||
dnf install -y nodejs
|
||||
sudo -u deploy bash -lc 'command -v node; command -v npm; node -v; npm -v'
|
||||
```
|
||||
|
||||
大陆服务器 `npm ci` 可能访问 npm 官方源超时。本次部署在 `/etc/tiku-saas/deploy.env` 中使用可配置 npm registry 和重试参数:
|
||||
|
||||
```bash
|
||||
NPM_REGISTRY=https://registry.npmmirror.com
|
||||
NPM_FETCH_RETRIES=5
|
||||
NPM_FETCH_RETRY_MINTIMEOUT=20000
|
||||
NPM_FETCH_RETRY_MAXTIMEOUT=120000
|
||||
NPM_FETCH_TIMEOUT=300000
|
||||
```
|
||||
|
||||
截至 2026-07-01 21:39,`sudo -u deploy /opt/tiku-saas/bin/deploy.sh` 已完成:
|
||||
|
||||
- Gitea `main` 拉取到 `/opt/tiku-saas/repo`。
|
||||
- `npm ci` 安装依赖。
|
||||
- `npm run security:repo`,结果 0 finding。
|
||||
- `node scripts/production-launch-gate-test.js`,通过。
|
||||
- API 和 worker 构建通过。
|
||||
- 学生端、租户后台、平台后台三套 Taro H5 构建通过。
|
||||
- H5 发布到 `/srv/tiku-saas/www/student`、`/srv/tiku-saas/www/tenant-admin`、`/srv/tiku-saas/www/platform-admin`。
|
||||
- 三个 `runtime-config.json` 已安装到各自 H5 根目录。
|
||||
|
||||
Taro H5 构建存在 webpack asset size warning,这是前端包体优化事项,不影响当前部署继续进行。后续可做拆包、按需加载和 KaTeX 字体裁剪。
|
||||
|
||||
## 服务器接管和故障恢复
|
||||
|
||||
2026-07-03 最新接管状态:
|
||||
|
||||
- Gitea `main` 已包含 PNVS 短信认证、后台登录修复、PNVS provider 配置/诊断脚本和旧题库视觉对齐版本,最新提交应至少是 `4fb4125`。
|
||||
- 服务器仓库仍在 `/opt/tiku-saas/repo`,归属用户应为 `deploy:deploy`。
|
||||
- 生产 API 已能启动,`https://api.tjszsb.com/api/tenant/resolve?host=app.tjszsb.com` 已返回 `master` 租户。
|
||||
- Supabase self-hosted 运行在 `/opt/tiku-saas/supabase-project`,Kong 通过 Nginx 暴露到 `https://supabase.tjszsb.com`。
|
||||
- 线上 H5 公开配置文件在 `/srv/tiku-saas/www/*/runtime-config.json`,密钥只允许放 `supabasePublishableKey` 这类公开 key。
|
||||
- 短信验证码登录生产必须使用 `AUTH_SMS_PROVIDER=aliyun-pnvs`。阿里云 AccessKey/Secret 只写入 `app_private.tenant_secrets(secret_scope='sms', secret_key='aliyun-pnvs')`,不要写进 `/etc/tiku-saas/api.env` 或 H5 `runtime-config.json`。
|
||||
|
||||
配置 PNVS provider 推荐用仓库脚本写入数据库,避免手写 SQL 时把密钥打进命令历史。生产环境建议临时关闭 shell history,再用 `read -s` 输入 AccessKeySecret:
|
||||
|
||||
```bash
|
||||
cd /opt/tiku-saas/repo
|
||||
set -a
|
||||
source /etc/tiku-saas/api.env
|
||||
set +a
|
||||
set +o history
|
||||
read -r -p 'Aliyun AccessKeyId: ' ALIYUN_ACCESS_KEY_ID
|
||||
read -r -s -p 'Aliyun AccessKeySecret: ' ALIYUN_ACCESS_KEY_SECRET; echo
|
||||
read -r -p 'PNVS SignName: ' ALIYUN_PNVS_SIGN_NAME
|
||||
read -r -p 'PNVS TemplateCode: ' ALIYUN_PNVS_TEMPLATE_CODE
|
||||
PNVS_TENANT_ID=00000000-0000-0000-0000-000000000001 \
|
||||
ALIYUN_ACCESS_KEY_ID="$ALIYUN_ACCESS_KEY_ID" \
|
||||
ALIYUN_ACCESS_KEY_SECRET="$ALIYUN_ACCESS_KEY_SECRET" \
|
||||
ALIYUN_PNVS_SIGN_NAME="$ALIYUN_PNVS_SIGN_NAME" \
|
||||
ALIYUN_PNVS_TEMPLATE_CODE="$ALIYUN_PNVS_TEMPLATE_CODE" \
|
||||
npm run configure:aliyun-pnvs
|
||||
unset ALIYUN_ACCESS_KEY_ID ALIYUN_ACCESS_KEY_SECRET ALIYUN_PNVS_SIGN_NAME ALIYUN_PNVS_TEMPLATE_CODE
|
||||
set -o history
|
||||
```
|
||||
|
||||
配置后先跑只读诊断,确认 env、`tenant_auth_providers` 和 `tenant_secrets` 对齐;输出只包含 AccessKey 长度和脱敏前后缀,不会打印密钥明文:
|
||||
|
||||
```bash
|
||||
cd /opt/tiku-saas/repo
|
||||
set -a
|
||||
source /etc/tiku-saas/api.env
|
||||
set +a
|
||||
PNVS_TENANT_ID=00000000-0000-0000-0000-000000000001 npm run diagnose:aliyun-pnvs
|
||||
```
|
||||
|
||||
如果 `readiness:production:db` 报 `legacy_sms_provider`,先 dry-run 查看仍处于 `active/testing` 的传统短信 provider,再确认停用。这个脚本只会处理 `aliyun`、`aliyun-sms`、`tencent`、`tencent-sms` 等旧短信 auth provider,不会改 PNVS 行:
|
||||
|
||||
```bash
|
||||
cd /opt/tiku-saas/repo
|
||||
set -a
|
||||
source /etc/tiku-saas/api.env
|
||||
set +a
|
||||
PNVS_TENANT_ID=00000000-0000-0000-0000-000000000001 npm run disable:legacy-sms-providers
|
||||
PNVS_TENANT_ID=00000000-0000-0000-0000-000000000001 npm run disable:legacy-sms-providers -- --apply
|
||||
```
|
||||
|
||||
接管服务器时先做只读检查:
|
||||
|
||||
```bash
|
||||
cd /opt/tiku-saas/repo
|
||||
sudo -u deploy git status --short
|
||||
sudo -u deploy git log -3 --oneline
|
||||
sudo -u deploy git remote -v
|
||||
systemctl status tiku-api --no-pager -l
|
||||
systemctl status tiku-worker --no-pager -l
|
||||
docker compose -f /opt/tiku-saas/supabase-project/docker-compose.yml ps
|
||||
```
|
||||
|
||||
Gitea SSH 使用 `2222` 端口,推荐服务器 `deploy` 用户的 remote 使用完整 SSH URL:
|
||||
|
||||
```bash
|
||||
sudo -u deploy git -C /opt/tiku-saas/repo remote set-url origin ssh://git@git.gongxue100.com:2222/chenhaogxjy/tiku-supabase.git
|
||||
sudo -u deploy ssh -o BatchMode=yes -T -p 2222 git@git.gongxue100.com
|
||||
sudo -u deploy git -C /opt/tiku-saas/repo pull origin main
|
||||
```
|
||||
|
||||
也可以写 `/home/deploy/.ssh/config`,但必须包含 `Port 2222`:
|
||||
|
||||
```sshconfig
|
||||
Host git.gongxue100.com
|
||||
HostName git.gongxue100.com
|
||||
User git
|
||||
Port 2222
|
||||
IdentityFile /home/deploy/.ssh/tiku_saas_deploy
|
||||
IdentitiesOnly yes
|
||||
```
|
||||
|
||||
如果 Taro 构建长时间没有输出,先判断它是真在编译还是已经卡死。构建中的 Taro/webpack 可能会有一段时间安静,但如果 `dist` 目录大小和最近修改时间 30 秒以上都不变,就按卡住处理:
|
||||
|
||||
```bash
|
||||
ps -eo pid,ppid,user,stat,etime,%cpu,%mem,cmd | grep -E 'npm|node|taro|webpack' | grep -v grep
|
||||
du -sh /opt/tiku-saas/repo/apps/taro/dist/h5-student
|
||||
sleep 30
|
||||
du -sh /opt/tiku-saas/repo/apps/taro/dist/h5-student
|
||||
find /opt/tiku-saas/repo/apps/taro/dist/h5-student -type f -mmin -5 | head -20
|
||||
```
|
||||
|
||||
确认卡住后,先在原终端 `Ctrl+C`。如果仍有残留 Taro 构建进程,再只结束这条构建链路,不要杀生产 API、Supabase 或其它 Node 服务:
|
||||
|
||||
```bash
|
||||
ps -eo pid,ppid,user,stat,etime,%cpu,%mem,cmd | grep -E 'npm run build:taro|taro build --type h5|webpack' | grep -v grep
|
||||
kill <pid>
|
||||
sleep 3
|
||||
kill -9 <pid>
|
||||
```
|
||||
|
||||
然后清理单端产物并带 CI/内存参数重跑。先单独跑学生端,成功后再跑另外两端:
|
||||
|
||||
```bash
|
||||
cd /opt/tiku-saas/repo
|
||||
rm -rf apps/taro/dist/h5-student
|
||||
sudo -u deploy env CI=1 NODE_OPTIONS="--max-old-space-size=4096" npm run build:taro:h5:student
|
||||
|
||||
rm -rf apps/taro/dist/h5-tenant-admin apps/taro/dist/h5-platform-admin
|
||||
sudo -u deploy env CI=1 NODE_OPTIONS="--max-old-space-size=4096" npm run build:taro:h5:tenant
|
||||
sudo -u deploy env CI=1 NODE_OPTIONS="--max-old-space-size=4096" npm run build:taro:h5:platform
|
||||
```
|
||||
|
||||
三端构建成功后再发布:
|
||||
服务器长期更新命令可以继续保持:
|
||||
|
||||
```bash
|
||||
sudo -u deploy /opt/tiku-saas/bin/deploy.sh
|
||||
```
|
||||
|
||||
如果只是想接管代码开发,不要从服务器 `apps/taro/dist` 或 `/srv/tiku-saas/www` 拷贝产物;它们只是发布结果,源码以 Gitea `main` 为准。
|
||||
但首次发布当前基线前,必须先升级 `/opt/tiku-saas/bin/deploy.sh`、部署配置、API/Worker env 和 systemd units。发布脚本不会自动更新自己,也不会自动安装 Nginx 或 systemd 模板。
|
||||
|
||||
## 首次安装
|
||||
## 发布能力与边界
|
||||
|
||||
1. 安装基础组件:Docker、Docker Compose、Node.js 20+、Nginx、Certbot、Git、rsync、flock。
|
||||
2. 按 Supabase 官方 self-hosting Docker 文档部署 Supabase。生产必须启用 HTTPS 反向代理,Supabase 官方也要求生产自托管部署使用 HTTPS。
|
||||
3. 把本目录模板复制到服务器:
|
||||
新版生产部署器会:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/tiku-saas/bin /etc/tiku-saas/runtime-config
|
||||
sudo cp scripts/deploy/bin/deploy.sh /opt/tiku-saas/bin/deploy.sh
|
||||
sudo cp scripts/deploy/env/deploy.env.example /etc/tiku-saas/deploy.env
|
||||
sudo cp scripts/deploy/env/api.env.example /etc/tiku-saas/api.env
|
||||
sudo cp scripts/deploy/env/worker.env.example /etc/tiku-saas/worker.env
|
||||
sudo cp scripts/deploy/runtime-config/h5-student.runtime-config.example.json /etc/tiku-saas/runtime-config/h5-student.runtime-config.json
|
||||
sudo cp scripts/deploy/runtime-config/h5-tenant-admin.runtime-config.example.json /etc/tiku-saas/runtime-config/h5-tenant-admin.runtime-config.json
|
||||
sudo cp scripts/deploy/runtime-config/h5-platform-admin.runtime-config.example.json /etc/tiku-saas/runtime-config/h5-platform-admin.runtime-config.json
|
||||
sudo chmod 700 /opt/tiku-saas/bin/deploy.sh
|
||||
sudo chmod 600 /etc/tiku-saas/*.env /etc/tiku-saas/runtime-config/*.json
|
||||
1. 获取固定分支的最新 commit,并在独立候选 release 安装锁定依赖。
|
||||
2. 运行 TypeScript、仓库安全扫描、runtime audit 和 Taro 供应链审计。
|
||||
3. 构建 API、Worker、学生 H5、租户后台 H5、平台后台 H5。
|
||||
4. 注入三端公开 runtime config,运行严格 guard、manifest、25 项静态 smoke 和 33 项真实浏览器交互 smoke。
|
||||
5. 运行生产 env readiness;可选执行 migration;随后运行数据库 readiness。
|
||||
6. 使用与 commit、artifact 和 SHA-256 绑定的真实 production launch evidence。
|
||||
7. 原子切换应用与 Web release,重启服务,验证 API `/health` 和线上 H5 hash。
|
||||
8. 失败时恢复上一份代码和 Web release。
|
||||
|
||||
脚本不会:
|
||||
|
||||
- 创建数据库或对象存储备份。
|
||||
- 回滚已经提交的 migration。
|
||||
- 自动更新 `/etc/systemd/system`、宝塔 Nginx 或 `/etc/tiku-saas/*.env`。
|
||||
- 逐一确认所有 Worker backlog、Provider、外部告警和业务数据正确性。
|
||||
- 自动创建首个平台超管。
|
||||
|
||||
因此 migration 必须先备份并演练向后兼容。代码/Web 回滚不能被当作数据库回滚。
|
||||
|
||||
## 域名与目录
|
||||
|
||||
参考域名:
|
||||
|
||||
```text
|
||||
api.tjszsb.com Node.js API
|
||||
app.tjszsb.com 学生 H5
|
||||
admin.tjszsb.com 租户后台 H5
|
||||
console.tjszsb.com 平台后台 H5
|
||||
supabase.tjszsb.com Supabase Gateway/Auth/Data API
|
||||
studio.tjszsb.com Supabase Studio,必须限制来源
|
||||
```
|
||||
|
||||
4. 编辑 `/etc/tiku-saas/*.env` 和 `/etc/tiku-saas/runtime-config/*.json`,填入真实生产配置。
|
||||
5. 安装 systemd 服务:
|
||||
现有生产兼容布局:
|
||||
|
||||
```bash
|
||||
sudo cp scripts/deploy/systemd/tiku-api.service /etc/systemd/system/tiku-api.service
|
||||
sudo cp scripts/deploy/systemd/tiku-worker.service /etc/systemd/system/tiku-worker.service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable tiku-api tiku-worker
|
||||
```text
|
||||
/opt/tiku-saas/source Gitea 源码副本,只用于 fetch/build
|
||||
/opt/tiku-saas/releases 版本化候选应用
|
||||
/opt/tiku-saas/current 当前应用 release 软链接
|
||||
/opt/tiku-saas/repo systemd 当前运行副本
|
||||
/opt/tiku-saas/bin/deploy.sh 服务器外置兼容部署器
|
||||
/srv/tiku-saas/www 当前三端 Web release 软链接
|
||||
/srv/tiku-saas/www-releases 版本化 Web release
|
||||
/etc/tiku-saas/deploy.env 部署配置和只读 Gitea 凭据
|
||||
/etc/tiku-saas/api.env API 生产 env
|
||||
/etc/tiku-saas/worker.env Worker 生产 env
|
||||
/etc/tiku-saas/runtime-config/ 三端公开 runtime config
|
||||
/etc/tiku-saas/production-launch-evidence.json
|
||||
/etc/tiku-saas/launch-artifacts/ 与 evidence 配套的证据文件
|
||||
```
|
||||
|
||||
6. 安装 Nginx 配置:
|
||||
根部署器使用 `/opt/tiku-saas/shared/` 保存 deploy env、readiness env、runtime config 和 evidence。systemd 模板目前仍从 `/etc/tiku-saas/api.env` 与 `/etc/tiku-saas/worker.env` 读取运行配置,因此使用根脚本时也必须维护这两个文件;`shared/.env` 只用于候选 release 的 readiness,关键 API 配置必须与 `/etc/tiku-saas/api.env` 保持一致,避免双配置漂移。现有服务器优先使用兼容入口,减少这项差异。
|
||||
|
||||
```bash
|
||||
sudo cp scripts/deploy/nginx/tjszsb.com.conf.example /etc/nginx/sites-available/tiku-saas.conf
|
||||
sudo ln -s /etc/nginx/sites-available/tiku-saas.conf /etc/nginx/sites-enabled/tiku-saas.conf
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
## 凭据
|
||||
|
||||
- 已经出现在聊天、工单、截图或日志里的 token 必须吊销。
|
||||
- 服务器优先使用只读 SSH deploy key;Gitea SSH 端口为 `2222`。
|
||||
- 使用 HTTPS 时,token 只放权限为 `600/640` 的服务器 env,由临时 `GIT_ASKPASS` 注入。
|
||||
- token 不得写入 Git remote、脚本、README 或命令历史。
|
||||
- `DATABASE_ADMIN_URL`、`DATABASE_MIGRATION_URL` 只从密码管理器临时注入,不长期写入 deploy/API/Worker env。
|
||||
|
||||
SSH remote:
|
||||
|
||||
```text
|
||||
ssh://git@git.gongxue100.com:2222/chenhaogxjy/tiku-supabase.git
|
||||
```
|
||||
|
||||
7. 申请 HTTPS 证书:
|
||||
## 新测试服务器
|
||||
|
||||
```bash
|
||||
sudo certbot --nginx -d api.tjszsb.com -d app.tjszsb.com -d admin.tjszsb.com -d console.tjszsb.com -d supabase.tjszsb.com -d studio.tjszsb.com
|
||||
测试服务器必须与生产完全隔离:
|
||||
|
||||
```text
|
||||
/opt/tiku-saas-staging
|
||||
/srv/tiku-saas-staging
|
||||
/etc/tiku-saas-staging
|
||||
staging-api.example.com
|
||||
staging-app.example.com
|
||||
staging-admin.example.com
|
||||
staging-console.example.com
|
||||
独立 PostgreSQL/Supabase、Auth、bucket 和 Provider 测试账号
|
||||
```
|
||||
|
||||
## Gitea 凭证
|
||||
数据库安全标记必须是:
|
||||
|
||||
优先推荐 SSH deploy key。若暂时使用 Gitea token,必须新建一个只读部署 token,并写入 `/etc/tiku-saas/deploy.env`,不要把 token 写进脚本、Git remote、命令历史或 README。
|
||||
|
||||
已经在聊天、工单、截图里出现过的 token 都应当视为暴露,正式上云前请立即吊销并重新生成。
|
||||
|
||||
`deploy.sh` 会通过临时 `GIT_ASKPASS` 给 `git clone/fetch` 提供账号和 token,避免 token 出现在 `git remote -v` 里。
|
||||
|
||||
## 更新发布
|
||||
|
||||
服务器上执行:
|
||||
|
||||
```bash
|
||||
sudo -u deploy /opt/tiku-saas/bin/deploy.sh
|
||||
```text
|
||||
environment=staging
|
||||
allow_destructive_tests=false
|
||||
```
|
||||
|
||||
脚本会执行:
|
||||
API 与 Worker 应继续使用 `NODE_ENV=production`,这样能验证生产配置 fail-fast。staging 不能使用 production 数据库、bucket、支付/短信密钥或真实用户流量,也不能运行 `supabase db reset`、`db:smoke-seed:test`、`test:api`、`test:rls` 和会写入集成夹具的 Worker 测试。
|
||||
|
||||
1. 获取 `main` 最新代码。
|
||||
2. `npm ci` 安装锁定依赖。
|
||||
3. 运行仓库安全扫描和生产上线门禁测试。
|
||||
4. 构建 API、worker、学生 H5、租户后台 H5、平台后台 H5。
|
||||
5. 用 `rsync --delete` 发布静态产物。
|
||||
6. 复制服务器本地 `runtime-config.json` 到对应 Web 根目录。
|
||||
7. 重启 `tiku-api` 和 `tiku-worker`。
|
||||
8. 输出当前发布的 Git commit。
|
||||
当前仓库没有经过验证的一键 staging profile。两套 deploy 脚本在 production 模式下都会强制真实 launch gate,launch evidence 也不能用本地 mock 伪造。首次测试服务器采用下面的分阶段 bootstrap;在 staging profile 被单独实现和验证前,不要直接套用生产 `/opt/tiku-saas`、`/srv/tiku-saas` 和 `/etc/tiku-saas` 路径。
|
||||
|
||||
## 上线前检查
|
||||
|
||||
每次正式放量前至少执行:
|
||||
### 1. 固定候选 commit
|
||||
|
||||
```bash
|
||||
npm run security:repo
|
||||
node scripts/production-launch-gate-test.js
|
||||
node scripts/launch-persona-smoke-test.js
|
||||
sudo install -d -o deploy -g deploy /opt/tiku-saas-staging/source
|
||||
sudo -u deploy git clone \
|
||||
ssh://git@git.gongxue100.com:2222/chenhaogxjy/tiku-supabase.git \
|
||||
/opt/tiku-saas-staging/source
|
||||
sudo -u deploy git -C /opt/tiku-saas-staging/source checkout <reviewed-commit-sha>
|
||||
```
|
||||
|
||||
不要在验证期间继续移动候选分支。
|
||||
|
||||
### 2. 安装与构建预检
|
||||
|
||||
```bash
|
||||
cd /opt/tiku-saas-staging/source
|
||||
sudo -u deploy npm ci --workspaces --include-workspace-root --include=dev
|
||||
sudo -u deploy npm run check:api
|
||||
sudo -u deploy npm run check:worker
|
||||
sudo -u deploy npm run check:taro
|
||||
sudo -u deploy npm run security:repo
|
||||
sudo -u deploy npm run audit:runtime
|
||||
sudo -u deploy npm run audit:taro:supply-chain
|
||||
sudo -u deploy npm run build:api
|
||||
sudo -u deploy npm run build:worker
|
||||
sudo -u deploy npm run build:taro:h5:student
|
||||
sudo -u deploy npm run build:taro:h5:tenant
|
||||
sudo -u deploy npm run build:taro:h5:platform
|
||||
```
|
||||
|
||||
服务器必须安装 Chrome/Chromium,或设置 `TARO_H5_SMOKE_BROWSER` 指向受支持浏览器。随后运行:
|
||||
|
||||
```bash
|
||||
sudo -u deploy npm run smoke:taro:h5
|
||||
sudo -u deploy env TARO_H5_INTERACTION_OUTPUT_DIR=/tmp/tiku-h5-staging \
|
||||
npm run smoke:taro:h5:interaction
|
||||
```
|
||||
|
||||
这一步只证明候选产物和本地 mock 旅程,不是生产 evidence。
|
||||
|
||||
### 3. 数据库 bootstrap 与 migration
|
||||
|
||||
先创建数据库和对象存储快照,再 dry-run runtime role 计划:
|
||||
|
||||
```bash
|
||||
cd /opt/tiku-saas-staging/source
|
||||
npm run bootstrap:db-runtime-roles
|
||||
```
|
||||
|
||||
由真正 PostgreSQL superuser 应用一次:
|
||||
|
||||
```bash
|
||||
DATABASE_ADMIN_URL='<secret-managed-superuser-url>' \
|
||||
npm run bootstrap:db-runtime-roles -- \
|
||||
--apply --confirm=BOOTSTRAP_BACKEND_RUNTIME_ROLES
|
||||
```
|
||||
|
||||
bootstrap 不设置角色密码。用密码管理器为 `tiku_api`、`tiku_worker` 设置独立强密码,再把相应连接分别写入 staging API/Worker env。
|
||||
|
||||
全新数据库在 migrations 后没有业务租户数据,生产 readiness 会因没有 active tenant 而阻断。使用受控管理流程创建 staging 的 master tenant、active domain、branding/settings 和必要 Provider 配置;不要执行 `supabase/seed.sql`,它是本地开发 seed,会把数据库标为 `local` 并写入 mock 数据。
|
||||
|
||||
由标准 migration role 应用迁移:
|
||||
|
||||
```bash
|
||||
DATABASE_MIGRATION_URL='<secret-managed-migration-url>' \
|
||||
supabase db push --db-url "$DATABASE_MIGRATION_URL"
|
||||
```
|
||||
|
||||
然后使用 API 运行角色验证:
|
||||
|
||||
```bash
|
||||
set -a
|
||||
source /etc/tiku-saas-staging/api.env
|
||||
set +a
|
||||
npm run readiness:production
|
||||
```
|
||||
|
||||
接入真实生产配置后,还要在服务器上补跑:
|
||||
|
||||
```bash
|
||||
npm run readiness:production:db
|
||||
npm run smoke:auth:remote
|
||||
SMS_SMOKE_API_BASE_URL=https://api.tjszsb.com SMS_SMOKE_TENANT_ID=00000000-0000-0000-0000-000000000001 SMS_SMOKE_PHONE=replace-with-real-phone SMS_SMOKE_ORIGIN=https://admin.tjszsb.com npm run smoke:sms-login:remote -- --write docs/refactor/launch-artifacts/sms-pnvs-remote-smoke.json
|
||||
npm run perf:api:local
|
||||
```
|
||||
|
||||
如果要同时验证手机号绑定也走 PNVS provider verification,准备一个未绑定测试手机号后执行:
|
||||
migration 是前向操作。失败时按备份恢复方案处理,不依赖 deploy symlink 回滚。
|
||||
|
||||
### 4. runtime config 与受控激活
|
||||
|
||||
从 `scripts/deploy/runtime-config/*.example.json` 创建 staging 文件。浏览器 H5 使用 Origin 解析租户时,`tenantCode` 保持空字符串;只允许公开 HTTPS URL 和 Supabase publishable key。
|
||||
|
||||
在尚未具备 staging 原子发布 profile 时,先由运维在隔离路径安装 systemd/Nginx,明确每一个 WorkingDirectory、EnvironmentFile、端口、域名和 Web root 都指向 `*-staging`。不得直接复制当前生产 unit 后仍保留 `/opt/tiku-saas/repo` 或 `/etc/tiku-saas`。
|
||||
|
||||
完成真实 staging Auth/CORS/Provider/三类 persona、Worker 和线上 H5 检查后,将报告保存到 staging 自己的 evidence bundle。production launch evidence 仍只能由最终生产候选生成,不能从 staging 复制冒充。
|
||||
|
||||
## 现有服务器一次性升级
|
||||
|
||||
### 1. 冻结与备份
|
||||
|
||||
1. 将完整基线合并到 Gitea,记录待部署 SHA。
|
||||
2. 备份 PostgreSQL、对象存储、`/etc/tiku-saas`、旧部署脚本、旧运行目录和宝塔 Nginx 配置。
|
||||
3. 验证备份可读,并记录数据库恢复与代码/Web 回滚步骤。
|
||||
4. 首次 migration 推荐独立执行“备份 -> migration -> DB readiness -> evidence”,正式应用发布时恢复 `RUN_DB_MIGRATIONS=false`。
|
||||
|
||||
### 2. 准备 source checkout
|
||||
|
||||
从一个不依赖旧部署脚本的临时目录获取新代码:
|
||||
|
||||
```bash
|
||||
SMS_SMOKE_API_BASE_URL=https://api.tjszsb.com SMS_SMOKE_TENANT_ID=00000000-0000-0000-0000-000000000001 SMS_SMOKE_PHONE=replace-with-login-phone SMS_SMOKE_BIND_PHONE=replace-with-bind-phone SMS_SMOKE_ORIGIN=https://admin.tjszsb.com npm run smoke:sms-login:remote -- --write docs/refactor/launch-artifacts/sms-pnvs-remote-smoke.json
|
||||
sudo install -d -o deploy -g deploy /opt/tiku-saas/source
|
||||
sudo -u deploy git clone \
|
||||
ssh://git@git.gongxue100.com:2222/chenhaogxjy/tiku-supabase.git \
|
||||
/opt/tiku-saas/source
|
||||
sudo -u deploy git -C /opt/tiku-saas/source checkout <reviewed-commit-sha>
|
||||
```
|
||||
|
||||
压测必须在目标云服务器、目标数据库参数、目标对象存储和目标 Nginx 配置下重新计算,本地 Windows 压测数据只能作为开发参考。
|
||||
若目录已存在,只允许 clean checkout:
|
||||
|
||||
## 关键安全要求
|
||||
```bash
|
||||
sudo -u deploy git -C /opt/tiku-saas/source status --short
|
||||
sudo -u deploy git -C /opt/tiku-saas/source fetch origin main --prune
|
||||
sudo -u deploy git -C /opt/tiku-saas/source checkout main
|
||||
sudo -u deploy git -C /opt/tiku-saas/source merge --ff-only origin/main
|
||||
```
|
||||
|
||||
- 前端只保存 `supabasePublishableKey`,严禁出现 service role、数据库密码、短信密钥、支付私钥。
|
||||
- 自研业务 API 默认只接受 Supabase JWT 或迁移期受控 app session,不允许前端携带平台管理密钥。
|
||||
- API、worker、Supabase、Nginx 日志要开启轮转,避免磁盘被日志打满。
|
||||
- 数据库至少每日备份,正式放量前要完成一次恢复演练。
|
||||
- 支付回调、短信回调、对象存储回调必须使用 HTTPS 域名,并在 API 层校验签名和租户归属。
|
||||
- Supabase Studio 必须限制访问来源。
|
||||
### 3. 升级外置部署脚本
|
||||
|
||||
先备份,再安装兼容入口:
|
||||
|
||||
```bash
|
||||
sudo cp -a /opt/tiku-saas/bin/deploy.sh \
|
||||
/opt/tiku-saas/bin/deploy.sh.backup-$(date +%Y%m%d%H%M%S)
|
||||
|
||||
sudo install -o root -g deploy -m 0750 \
|
||||
/opt/tiku-saas/source/scripts/deploy/bin/deploy.sh \
|
||||
/opt/tiku-saas/bin/deploy.sh
|
||||
```
|
||||
|
||||
不要期待仓库 pull 自动更新 `/opt/tiku-saas/bin/deploy.sh`。
|
||||
|
||||
### 4. 更新配置
|
||||
|
||||
备份 `/etc/tiku-saas/deploy.env`、`api.env` 和 `worker.env`,再逐项 diff 模板,不要覆盖真实 secrets:
|
||||
|
||||
```bash
|
||||
diff -u /etc/tiku-saas/deploy.env \
|
||||
/opt/tiku-saas/source/scripts/deploy/env/deploy.env.example || true
|
||||
diff -u /etc/tiku-saas/api.env \
|
||||
/opt/tiku-saas/source/scripts/deploy/env/api.env.example || true
|
||||
diff -u /etc/tiku-saas/worker.env \
|
||||
/opt/tiku-saas/source/scripts/deploy/env/worker.env.example || true
|
||||
```
|
||||
|
||||
必须确认:
|
||||
|
||||
```text
|
||||
SOURCE_REPO_DIR=/opt/tiku-saas/source
|
||||
REPO_DIR=/opt/tiku-saas/repo
|
||||
RELEASES_DIR=/opt/tiku-saas/releases
|
||||
WWW_ROOT=/srv/tiku-saas/www
|
||||
WWW_RELEASES_DIR=/srv/tiku-saas/www-releases
|
||||
RUN_TARO_SUPPLY_CHAIN_AUDIT=true
|
||||
RUN_DB_READINESS=true
|
||||
RUN_LAUNCH_GATE=true
|
||||
SYSTEMD_UNITS="tiku-api.service tiku-workers.target"
|
||||
HEALTHCHECK_URL=http://127.0.0.1:8787/health
|
||||
```
|
||||
|
||||
API `DATABASE_URL` 必须使用 `tiku_api`,Worker 必须使用 `tiku_worker`。真实 env 的权限推荐为 `root:deploy 0640`。
|
||||
|
||||
Provider 密钥不要仅凭 env 模板判断“已经配置完成”。PNVS、OAuth、支付和租户级密钥以 `app_private.tenant_secrets` 及对应 Provider 配置为真实来源,必须通过仓库配置/诊断脚本和 production readiness 验证。对象存储及 Worker scanner 等进程级配置才由 API/Worker env 提供。
|
||||
|
||||
连接池要按进程总量预算:默认 9 个常驻 Worker 若每个 `DB_POOL_MAX=5`,仅 Worker 上限约 45 个连接;再加 API、timer/oneshot、Supabase 内部服务和运维连接。正式启用前应结合 PostgreSQL `max_connections` 和 PgBouncer 配额调整,而不是逐个进程孤立设置。
|
||||
|
||||
### 5. 升级 Worker 调度
|
||||
|
||||
不要使用通配复制后遗留旧 unit。显式安装当前清单:
|
||||
|
||||
```bash
|
||||
sudo systemctl stop tiku-worker.service 2>/dev/null || true
|
||||
sudo systemctl disable tiku-worker.service 2>/dev/null || true
|
||||
sudo rm -f /etc/systemd/system/tiku-worker.service
|
||||
|
||||
for unit in \
|
||||
tiku-api.service \
|
||||
tiku-worker@.service \
|
||||
tiku-worker-job@.service \
|
||||
tiku-worker-monthly-usage.service \
|
||||
tiku-worker-monthly-usage.timer \
|
||||
tiku-worker-platform-audit-alerts.timer \
|
||||
tiku-worker-platform-billing.timer \
|
||||
tiku-worker-platform-dunning.timer \
|
||||
tiku-worker-platform-usage.timer \
|
||||
tiku-worker-student-supervision.timer \
|
||||
tiku-workers.target
|
||||
do
|
||||
sudo install -o root -g root -m 0644 \
|
||||
"/opt/tiku-saas/source/scripts/deploy/systemd/$unit" \
|
||||
"/etc/systemd/system/$unit"
|
||||
done
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable tiku-api.service tiku-workers.target
|
||||
```
|
||||
|
||||
不要在新的应用 release 尚未构建并同步到 `/opt/tiku-saas/repo` 前启动 `tiku-workers.target`。
|
||||
|
||||
连续 Worker 为 CRM、commerce、provider bills、催缴通知、审计通知、assets、imports、public banks 和 exports;定时任务负责计费、用量、月结超额、催缴、审计告警和学习督导。
|
||||
|
||||
### 6. systemd 权限
|
||||
|
||||
部署器以 `deploy` 用户运行,但需要重启 `tiku-api.service` 和 `tiku-workers.target`。首次升级前检查:
|
||||
|
||||
```bash
|
||||
sudo -u deploy systemctl is-active tiku-api.service
|
||||
sudo -u deploy systemctl restart tiku-api.service
|
||||
```
|
||||
|
||||
第二条如果要求交互认证,部署会在切换阶段失败。不要给 `deploy` `NOPASSWD: ALL`。选择其一:
|
||||
|
||||
- 用受审 root wrapper 只允许 restart/is-active 这两个顶层 unit,并把 `RESTART_COMMAND` 指向 wrapper。
|
||||
- 配置精确的 PolicyKit 规则,只允许 deploy 管理本项目 unit。
|
||||
- 由 root 执行受控部署器,同时确保 clone/npm/release 文件所有权仍为 deploy,并重新验证脚本权限模型。
|
||||
|
||||
完成最小权限方案后,必须在非交互会话中验证。
|
||||
|
||||
### 7. 数据库、runtime config 与 evidence
|
||||
|
||||
按“新测试服务器”中的数据库步骤完成:
|
||||
|
||||
1. superuser runtime role/extension bootstrap。
|
||||
2. 为 `tiku_api/tiku_worker` 设置独立密码。
|
||||
3. 标准 migration role 应用 migration。
|
||||
4. `readiness:production` 和 `readiness:production:db`。
|
||||
|
||||
三端 runtime config 路径:
|
||||
|
||||
```text
|
||||
/etc/tiku-saas/runtime-config/h5-student.runtime-config.json
|
||||
/etc/tiku-saas/runtime-config/h5-tenant-admin.runtime-config.json
|
||||
/etc/tiku-saas/runtime-config/h5-platform-admin.runtime-config.json
|
||||
```
|
||||
|
||||
`tenantCode` 默认留空,由三个生产 Origin 解析租户;只有明确的固定租户预览/小程序模式才填写。
|
||||
|
||||
production evidence 必须绑定待发布 commit。兼容脚本默认读取:
|
||||
|
||||
```text
|
||||
/etc/tiku-saas/production-launch-evidence.json
|
||||
```
|
||||
|
||||
相对 artifact 路径从 evidence 所在目录解析,因此完整 bundle 应为:
|
||||
|
||||
```text
|
||||
/etc/tiku-saas/production-launch-evidence.json
|
||||
/etc/tiku-saas/launch-artifacts/*
|
||||
```
|
||||
|
||||
只复制 evidence JSON 而不复制 artifacts 会 fail closed。staging、本地 mock 或旧 commit 的 evidence 不能复用。
|
||||
|
||||
### 8. 宝塔/Nginx
|
||||
|
||||
宝塔服务器继续保留它管理的站点文件,不要直接套用普通 `/etc/nginx/sites-available` 命令。人工对照 `scripts/deploy/nginx/tjszsb.com.conf.example` 同步:
|
||||
|
||||
- `/srv/tiku-saas/www/{student,tenant-admin,platform-admin}` 三端路径。
|
||||
- SPA history fallback。
|
||||
- `runtime-config.json` `no-store`。
|
||||
- 带 hash 静态资源长期缓存。
|
||||
- API forwarded headers、body limit、超时和必要限流。
|
||||
- Supabase Gateway/Studio HTTPS 与 Studio 来源限制。
|
||||
|
||||
若宝塔站点根目录必须位于 `/www/wwwroot`,用受控软链接指向 `/srv/tiku-saas/www/*`,不要复制第二份静态文件形成漂移。
|
||||
|
||||
### 9. 正式执行
|
||||
|
||||
服务器需有 Node.js 20、npm、Git、rsync、curl、Supabase CLI,以及 Chrome/Chromium。浏览器不在标准路径时设置 `TARO_H5_SMOKE_BROWSER`。
|
||||
|
||||
先确认 source clean、evidence commit 和待发布 SHA 一致,再运行:
|
||||
|
||||
```bash
|
||||
sudo -u deploy /opt/tiku-saas/bin/deploy.sh
|
||||
```
|
||||
|
||||
如果本次数据库已独立迁移完成,保持:
|
||||
|
||||
```text
|
||||
RUN_DB_MIGRATIONS=false
|
||||
```
|
||||
|
||||
部署器在任何激活前完成候选构建和门禁;应用/Web 切换、服务重启、API health 或线上 H5 hash 失败会触发代码/Web回滚。
|
||||
|
||||
## 发布后验收
|
||||
|
||||
脚本只检查顶层 target active 和 API `/health`,发布后还必须人工运行:
|
||||
|
||||
```bash
|
||||
systemctl --failed --no-pager
|
||||
systemctl is-active tiku-api.service tiku-workers.target
|
||||
systemctl list-dependencies tiku-workers.target --no-pager
|
||||
systemctl list-timers 'tiku-worker-*' --all --no-pager
|
||||
systemctl status 'tiku-worker@*.service' --no-pager
|
||||
journalctl -u tiku-api.service -n 100 --no-pager
|
||||
journalctl -u 'tiku-worker@*.service' -n 200 --no-pager
|
||||
curl -fsS http://127.0.0.1:8787/health
|
||||
```
|
||||
|
||||
随后验证:
|
||||
|
||||
- 三个生产域名的 `index.html`、runtime config、登录和主入口。
|
||||
- `/api/tenant/resolve` 的 Origin/CORS。
|
||||
- 真实 Auth/JWKS、PNVS 短信、支付/退款回调、对象存储签名与扫描。
|
||||
- Worker backlog、失败重试、timer 下次执行时间和外部告警渠道。
|
||||
- 错误率、P95/P99、数据库连接池、慢 SQL、锁等待、磁盘和日志轮转。
|
||||
|
||||
## 回滚
|
||||
|
||||
自动回滚只覆盖应用代码和三端 Web:
|
||||
|
||||
```text
|
||||
/opt/tiku-saas/current
|
||||
/opt/tiku-saas/repo
|
||||
/srv/tiku-saas/www
|
||||
```
|
||||
|
||||
数据库 migration、对象存储写入、外部 Provider 状态和已产生业务事件不会自动回滚。数据库恢复必须使用发布前已验证的快照/备份,并由负责人单独决策。
|
||||
|
||||
手工代码/Web 回滚前,先记录失败 release 和日志,再将软链接切回上一 release、同步运行目录、重启服务并复核 API/H5。不要使用 `git reset --hard` 处理服务器运行目录。
|
||||
|
||||
## 安全检查清单
|
||||
|
||||
- [ ] 暴露 token 已吊销,服务器只读凭据已轮换。
|
||||
- [ ] 待发布 commit 已冻结,source checkout clean。
|
||||
- [ ] PostgreSQL、对象存储和 `/etc/tiku-saas` 已备份并验证可读。
|
||||
- [ ] `tiku_api/tiku_worker` bootstrap、独立密码和 migration role 已完成。
|
||||
- [ ] 三端 runtime config 只有公开字段,`tenantCode` 策略正确。
|
||||
- [ ] 旧 `tiku-worker.service` 已停止、禁用并删除。
|
||||
- [ ] 新 Worker units/timers/target 已安装,deploy 重启权限最小化。
|
||||
- [ ] Chrome/Chromium 可用于 33 项 H5 交互 smoke。
|
||||
- [ ] evidence commit、artifacts、hash 和人工 attestation 完整。
|
||||
- [ ] 宝塔/Nginx history fallback、缓存、CORS、CSP 和 forwarded headers 已复核。
|
||||
- [ ] 首个平台超管通过 Auth-bound bootstrap 创建并留有审计。
|
||||
- [ ] 发布后逐 Worker、timer、Provider、日志和监控验收完成。
|
||||
|
||||
## 参考
|
||||
|
||||
- Supabase self-hosting Docker: https://supabase.com/docs/guides/self-hosting/docker
|
||||
- Supabase reverse proxy and HTTPS: https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https
|
||||
- Supabase Auth self-hosting config: https://supabase.com/docs/guides/self-hosting/auth/config
|
||||
- Supabase self-hosted S3 storage: https://supabase.com/docs/guides/self-hosting/self-hosted-s3
|
||||
- [根 README](../../README.md)
|
||||
- [生产地基基线](../../docs/refactor/production-foundation-baseline-20260712.md)
|
||||
- [Taro H5 部署](../../docs/refactor/taro-h5-deployment.md)
|
||||
- [上线 evidence 模板](../../docs/refactor/production-launch-evidence.template.json)
|
||||
- [Supabase self-hosting](https://supabase.com/docs/guides/self-hosting/docker)
|
||||
- [Supabase HTTPS reverse proxy](https://supabase.com/docs/guides/self-hosting/self-hosted-proxy-https)
|
||||
|
||||
Reference in New Issue
Block a user