fix: stabilize external-db deployment and updates
Release / release (push) Canceled after 0s

This commit is contained in:
Qiufeng
2026-08-18 22:51:35 +08:00
parent 227c4b0129
commit 8c6c10eb85
22 changed files with 767 additions and 279 deletions
+45 -35
View File
@@ -8,7 +8,14 @@
## 本地开发
本地开发数据库由环境变量显式指定,启动 Java 服务:
本地开发数据库由环境变量显式指定,启动 Java 服务。仓库中的 `deploy/compose.yaml` 只是可选的本地开发夹具;
需要它时必须显式启用 `local-db` profile,生产安装器不会执行 Compose、创建 MySQL 或安装 MySQL 客户端:
```bash
docker compose -f deploy/compose.yaml --profile local-db up -d
```
随后启动 Java 服务:
```bash
cd backend
@@ -59,8 +66,9 @@ PostgreSQL 18 兼容工作继续冻结。
- **生产机不执行 `git clone`、`git pull` 或远程脚本拼接。** 源码仓库是
`https://git.awaioi.com/ERP-Team/kaidi.git`,生产安装和后台更新使用同一仓库生成的公开 Gitea Release。
- 安装器先读取 Gitea Release API,再下载 `release-manifest.json`、签名、公钥和压缩包,校验固定公钥指纹、RSA 签名、版本、文件名和 SHA-256;校验失败不会安装。
- 后台“获取版本”只查询 Release;“下载”才下载并校验;“立即更新并重启”才备份数据库、切换 `current` 并重启服务。更新器下载的是 Release 制品,不是 Git 工作树。
- 后台“获取版本”只查询 Release;“下载”才下载并校验;“立即更新并重启”才切换 `current` 并重启服务。更新器默认不访问数据库;如明确设置 `KAIDI_DB_BACKUP_MODE=mysqldump`,才会调用主机已有的备份工具。更新器下载的是 Release 制品,不是 Git 工作树。
- MySQL 是**已有数据库**,应用只通过向导写入的 `DB_URL`、`DB_USERNAME`、`DB_PASSWORD` 连接它;安装器不安装 MySQL、不创建数据库、不修改数据库服务。填写 `127.0.0.1` 表示 MySQL 与 Java 应用在同一台服务器,端口以实际监听端口为准,不默认假设 `3307`。
- 安装阶段只校验 JDBC 配置格式,不调用 `mysql`/`mariadb` 客户端,也不执行 `CREATE`、`INSERT`、`UPDATE`、`DELETE` 或 `DROP`。首次向导点击“完成安装”后,应用才会在**专用空 schema**中运行 Flyway 建表并初始化管理员;这是业务初始化,不是安装 MySQL 服务。在线更新默认跳过数据库备份;需要备份时由运维显式设置 `KAIDI_DB_BACKUP_MODE=mysqldump`,更新器只调用已有工具,不会安装数据库。
- `KAIDI_APP_PORT` 只决定 Java 回环监听端口,默认 `18080`;反向代理必须指向安装器输出的 `PROXY_TARGET`。安装器不会替你修改 Nginx 或宝塔站点配置。
- 发布归档使用无顶层目录的 `tar.gz`,只包含 `app.jar`、`public/`、`ops/`、`VERSION`;打包阶段禁用 macOS 扩展属性并拒绝开发数据库回退值。
@@ -68,14 +76,14 @@ PostgreSQL 18 兼容工作继续冻结。
当前支持的是 **i386/i486/i586/i686 + glibc + systemd + 可运行的 32 位 Java 17**。安装器会校验用户空间位数、Java 架构、glibc 和 `/lib/ld-linux.so.2`(兼容 `/lib32`、`/lib/i386-linux-gnu` 路径);musl 或缺少 32 位加载器的系统会在安装前明确失败,不会安装后才出现无法启动。
32 位服务器应使用首次访问 `/setup` 的向导输入外部 MySQL 8.4 连接信息,这条路径不需要在服务器安装 MySQL 客户端。在线更新前仍需准备与数据库兼容的 `mysqldump`;如果 32 位系统无法提供该客户端,应先关闭在线更新或从独立备份机执行数据库备份,不要在更新过程中临时安装数据库。
32 位服务器应使用首次访问 `/setup` 的向导输入外部 MySQL 8.4 连接信息,这条路径不需要在服务器安装 MySQL 客户端。在线更新默认不需要 `mysqldump`;如果要启用更新前备份,再确认 32 位系统能执行兼容的 `mysqldump`,否则保持默认 `skip` 或从独立备份机执行备份,不要临时安装数据库。
### systemd 一键安装(推荐)
先在宝塔面板停止并删除当前错误的 Java 项目,再执行:
```bash
curl -fsSL https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.41/install.sh | sudo env KAIDI_APP_PORT=18080 bash
curl -fsSL https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.42/install.sh | sudo env KAIDI_APP_PORT=18080 bash
```
该命令只安装程序运行所需的 systemd 单元,自动创建 `kaidi` 用户并检测现有 Java 17(包括
@@ -88,38 +96,39 @@ curl -fsSL https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-previe
随后执行一键清理:
```bash
curl -fsSL https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.41/purge.sh \
-o /tmp/kaidi-purge.sh \
&& curl -fsSL https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.41/SHA256SUMS \
-o /tmp/kaidi-SHA256SUMS \
&& (cd /tmp && grep ' purge.sh$' kaidi-SHA256SUMS | sha256sum -c -) \
&& sudo env KAIDI_PURGE_CONFIRM=DELETE_LOCAL_KAIDI_INSTALLATION bash /tmp/kaidi-purge.sh \
&& rm -f /tmp/kaidi-purge.sh /tmp/kaidi-SHA256SUMS
curl -fsSL 'https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.42/purge.sh' | sudo env KAIDI_PURGE_CONFIRM=DELETE_LOCAL_KAIDI_INSTALLATION bash
```
上面是一条完整命令:脚本通过管道直接交给 root 执行,不创建临时安装文件,避免终端自动换行导致 `-o` 参数丢失。
如果需要连同本地恢复备份一起删除(确认不再需要回滚后再执行),在同一条命令中增加
`KAIDI_PURGE_DELETE_BACKUP=true`。卸载前必须先停止并删除宝塔中的 `kaidi-finance` Java 项目;宝塔的项目元数据、
Nginx/反向代理和外部 MySQL 属于外部资源,卸载程序不会误删它们。
清理脚本会先停止 systemd 和遗留 Kaidi 进程,将旧配置、文件存储、安装码以及已有数据库备份归档到
`/root/kaidi-reinstall-backups/`,再删除 `/opt/kaidi`、`/www/wwwroot/kaidi`、`/etc/kaidi`、
`/var/lib/kaidi`、`/var/lib/kaidi-update`、`/var/log/kaidi` 和三个 systemd 单元。恢复包权限固定为
`0600`,确认新安装及数据无误后再由 root 删除。脚本不删除外部 MySQL、系统 Java、Nginx 或宝塔站点配置;
新安装必须连接一个新的空 MySQL 数据库,旧数据库保留用于回滚。
### Preview.41 直链与宝塔手动部署
### Preview.42 直链与宝塔手动部署
本版不使用一键安装脚本。发布物是一个不带顶层目录的压缩包,下载后直接解压到版本目录,再由宝塔面板创建
Spring Boot 项目。数据库、JDK、Nginx 和宝塔本身都由运维人员准备;程序不会自动安装 MySQL 或任何第三方服务。
下载地址:
`https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.41/kaidi-finance-1.0.0-preview.41.tar.gz`
`https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.42/kaidi-finance-1.0.0-preview.42.tar.gz`
校验文件:`https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.41/SHA256SUMS`
校验文件:`https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.42/SHA256SUMS`
服务器要求:Linux + systemd、Java 17(宝塔项目选择 JDK 17)、可访问外部 MySQL 8.4.x;32 位 Linux 需要宿主机
服务器要求:Linux、Java 17(宝塔项目选择 JDK 17)、可访问外部 MySQL 8.4.x;**systemd 一键安装**还需要
systemd/systemd-analyze,**宝塔手动部署**不要求 systemd。32 位 Linux 需要宿主机
已经提供可运行的 32 位 Java 17。程序只连接已有数据库,不安装数据库客户端或数据库服务。初始化只需要
`bash`、`openssl`、`sha256sum` 和基础 Linux 工具;选择 systemd 在线更新前,另行准备 `curl`、`jq`、`flock`、`gzip`、`runuser`
以及与外部 MySQL 兼容的 `mysqldump`。安装器和更新器会优先使用 PATH 中的工具,也会探测宝塔常见的
`/www/server/mysql/bin/` 路径;如工具安装在其他位置,可分别设置 `KAIDI_MYSQL_CLIENT` 和
`bash`、`openssl`、`sha256sum` 和基础 Linux 工具;systemd 在线更新默认不需要数据库客户端。只有将
`KAIDI_DB_BACKUP_MODE` 设为 `mysqldump` 时,才需要 `curl`、`jq`、`flock`、`gzip`、`runuser` 和兼容的
`mysqldump`;安装器和更新器会优先使用 PATH 中的工具,也会探测宝塔常见的 `/www/server/mysql/bin/` 路径;如备份工具安装在其他位置,可设置
`KAIDI_MYSQLDUMP_BIN`,程序不会替你安装这些依赖。
更新器默认只下载、验签、切换和健康检查,不调用 Docker、不进入容器,也不创建或管理 MySQL 服务。
#### 1. 下载、校验、解压
@@ -127,7 +136,7 @@ Spring Boot 项目。数据库、JDK、Nginx 和宝塔本身都由运维人员
必须直接位于 `RELEASE_ROOT`,不能再嵌套一层目录。
```bash
VERSION=1.0.0-preview.41
VERSION=1.0.0-preview.42
APP_ROOT=/www/wwwroot/kaidi
RELEASE_ROOT="$APP_ROOT/releases/$VERSION"
sudo install -d -m 0755 "$RELEASE_ROOT"
@@ -218,29 +227,30 @@ curl -fsS http://127.0.0.1:18080/ | head
不要在宝塔项目仍运行时点击“系统治理 → 系统更新”,也不要让宝塔守护和 `kaidi-finance.service` 同时管理同一端口。
需要后台点击“获取版本 → 下载 → 立即更新并重启”的稳定流程时,使用上一节的 systemd 一键安装方式。
手动升级前请先由运维人员完成外部 MySQL 备份;程序不会安装 MySQL 或客户端,也不会修改反向代理配置。
手动升级由运维人员决定是否先做外部 MySQL 备份;程序不会安装 MySQL 或客户端,也不会修改反向代理配置。
后续版本仍按同样方式直接下载并解压到新的 `releases/<VERSION>`,保留可回滚的旧目录。
### Linux 32 位
压缩包本身不绑定 CPU 架构,关键是宿主机提供 glibc、systemd 和可运行的 32 位 Java 17。32 位主机不能在本机运行 64 位 JDK,也不应尝试在本机安装
MySQL 8.4;提前准备外部 MySQL,完成上述向导即可。选择 systemd 在线更新前,还必须确认宿主机能执行与数据库版本兼容的
`mysqldump`;宝塔手动模式只做手动制品替换和人工数据库备份。
MySQL 8.4;提前准备外部 MySQL,完成上述向导即可。systemd 在线更新默认不访问数据库;只有显式启用
`KAIDI_DB_BACKUP_MODE=mysqldump` 时才需要确认宿主机能执行与数据库版本兼容的工具。宝塔手动模式只做手动制品替换和人工数据库备份。
### 停用并移除程序
### 一键卸载
以下命令移除应用程序和服务,但保留 `/var/lib/kaidi`、`/var/lib/kaidi-update`、`/etc/kaidi` 以及数据库,
便于审计、备份或重新安装。确认数据备份前不要删除这些保留目录或外部 MySQL 数据。
反向代理由运维人员独立管理,停用程序不会修改其配置。
`purge.sh` 就是本项目的卸载程序:它会停止 Kaidi 进程、移除 systemd 单元、删除本地程序/配置/运行状态、
清理受管临时压缩包,并删除本次安装创建的 `kaidi` 服务账号;不会触碰外部 MySQL、Nginx、反向代理或系统 Java。
默认先把本地配置和运行数据保存到 root-only 恢复包,再删除受管路径。确认不需要回滚时,可在同一条命令中设置
`KAIDI_PURGE_DELETE_BACKUP=true`,实现本地受管文件和恢复包一并清除:
```bash
sudo systemctl disable --now kaidi-update.path kaidi-update.service kaidi-finance.service
sudo rm -f /etc/systemd/system/kaidi-finance.service /etc/systemd/system/kaidi-update.service /etc/systemd/system/kaidi-update.path
sudo systemctl daemon-reload
sudo rm -rf /opt/kaidi
curl -fsSL 'https://git.awaioi.com/ERP-Team/kaidi/releases/download/v1.0.0-preview.42/purge.sh' | sudo env KAIDI_PURGE_CONFIRM=DELETE_LOCAL_KAIDI_INSTALLATION KAIDI_PURGE_DELETE_BACKUP=true bash
```
执行前先在宝塔停止并删除 `kaidi-finance` Java 项目;宝塔面板元数据属于外部资源,必须由面板先停用,
否则守护进程会重新拉起 Java,卸载程序会明确报出原因而不误删其他服务。
## Release 与在线更新
首次建立发布仓库时生成一次签名密钥:
@@ -261,8 +271,8 @@ Actions 页面显示 “No matching online runner”,先启动并注册该标
Preview 属性由 SemVer 版本名表达。之后推送 tag 即会构建、测试、签名并发布:
```bash
git tag v1.0.0-preview.41
git push origin v1.0.0-preview.41
git tag v1.0.0-preview.42
git push origin v1.0.0-preview.42
```
在线更新仍使用独立的 TDesign 页面:系统管理员进入“系统治理 → 系统更新”。更新源由 root 在
@@ -277,11 +287,11 @@ git push origin v1.0.0-preview.41
2. 发现新版本后显示“立即更新”;管理员点击后才排队 `DOWNLOAD`。更新器下载 manifest、签名和应用包,执行 RSA、SHA-256、版本、
文件名和压缩包路径校验,通过后缓存到 `/var/lib/kaidi-update/cache/<version>`,业务服务继续运行。
3. 页面实时轮询并依次显示下载已排队、下载中、校验中和 `READY/下载完成`;只有下载完成后才显示“立即更新并重启”。
4. 管理员点击“立即更新并重启”,更新器预先调用宿主机已有的 `mysqldump`,备份权限为 `0600`,默认保留最近 5 份;程序不会安装 MySQL 或客户端。
4. 管理员点击“立即更新并重启”,更新器默认不访问数据库;如运维已将 `KAIDI_DB_BACKUP_MODE=mysqldump` 写入 `/etc/kaidi/update.env`,才会调用宿主机已有的 `mysqldump`,备份权限为 `0600`,默认保留最近 5 份。程序不会安装 MySQL 或客户端。
5. 更新器安装并保护新版本目录,原子切换 `/opt/kaidi/current`(宝塔手动部署才使用
`/www/wwwroot/kaidi/current`),停止并重启 systemd 管理的应用服务。
6. 健康端点、静态首页和运行版本全部通过后,页面等待 10 秒自动刷新;期间断线或命令响应丢失由前端状态重同步恢复。任一检查失败则切回上一应用版本,
保留数据库备份和事务证据供人工处理。
如果启用了 `mysqldump` 模式则保留数据库备份;否则保留事务证据供人工处理。
忙碌期间检查、下载和安装按钮保持禁用,防止重复请求;10 秒只用于成功后的页面刷新,不延迟服务端切换。数据库迁移必须至少保持一个版本向后兼容。
查看状态和日志:
@@ -314,7 +324,7 @@ cat /var/lib/kaidi-update/status.json
```bash
KAIDI_RELEASE_SIGNING_KEY=/secure/release-signing-private.pem \
KAIDI_TRUSTED_RELEASE_PUBLIC_KEY_SHA256=807c6aec1dc3f7ce494db16aa9d763c66f292033c38f328afd0390d2715a8cd9 \
./scripts/package-release.sh 1.0.0-preview.41
./scripts/package-release.sh 1.0.0-preview.42
KAIDI_TRUSTED_RELEASE_PUBLIC_KEY_SHA256=807c6aec1dc3f7ce494db16aa9d763c66f292033c38f328afd0390d2715a8cd9 \
./scripts/verify-release.sh dist/release
```