docs: document Linux and BaoTa deployment workflow

Add a root README and a current deployment guide covering local setup, versioned Linux packaging, manual BaoTa updates with backups and rollback, production verification, and miniapp API_BASE configuration.
This commit is contained in:
2026-11-04 21:32:39 +08:00
parent b854d2873e
commit abe543d4b2
3 changed files with 295 additions and 67 deletions
+23
View File
@@ -0,0 +1,23 @@
# 我们 past
微信小程序、Go 后端与管理端共用此仓库。Go 模块位于 `past-go/`,不是仓库根目录;管理端构建后嵌入后端二进制。
| 目录 | 用途 |
| --- | --- |
| `weapp/` | 微信小程序 |
| `past-go/` | Go 后端、配置模板和 Makefile |
| `past-go/web/admin/` | React 管理端 |
| `deploy/linux/` | 当前生产 systemd 服务和 Nginx 配置参考 |
## 开发与部署
**协同开发请先阅读 [Linux / 宝塔部署文档](past-go/deploy/README.md)**:包含首次准备、本地开发、打包上传、备份更新、线上验证和回滚命令。
- [后端配置与业务说明](past-go/README.md)
- [Windows 部署说明](past-go/deploy/windows/README.md)(当前生产环境使用 Linux)
生产域名:`https://we.sundynix.cn`;管理端:`https://we.sundynix.cn/backend/admin/login`。
小程序 `weapp/config/env.js` 只导出 `API_BASE`,不自动判断环境。开发时手动填本机或局域网地址,上传体验版、正式版前改成 `https://we.sundynix.cn/api`。
真实 `config.yaml`、`config.dev.yaml` 和支付证书不会随 Git 下发。新成员需向项目负责人领取配置与证书,或从示例文件配置自己的开发环境;现有服务器更新时保留线上配置、证书及数据。
+6 -2
View File
@@ -1,3 +1,7 @@
# 我们 past 后端
开发、打包、宝塔更新、验证与回滚步骤见 **[Linux / 宝塔部署文档](deploy/README.md)**。仓库总览见 [根目录 README](../README.md)。以下为配置与业务说明。
# 微信支付 API v3 # 微信支付 API v3
空间会员通过微信小程序 `wx.requestPayment` 支付,服务端使用官方 `wechatpay-go` SDK(与 plant-go 同样采用微信支付公钥验签模式)。线上域名为 `we.sundynix.cn`。 空间会员通过微信小程序 `wx.requestPayment` 支付,服务端使用官方 `wechatpay-go` SDK(与 plant-go 同样采用微信支付公钥验签模式)。线上域名为 `we.sundynix.cn`。
@@ -8,7 +12,7 @@
接口: 接口:
- `POST /api/storageCreateOrder`:传 `planKey: month/year`;价格由服务端收费设置决定。先持久化订单,再调用预下单,返回 `outTradeNo` 与 `payment` 签名参数。 - `POST /api/storageCreateOrder`:传服务端当前上架套餐的 `planKey`(见 `storageInfo`),并携带页面取得的 `expectedPriceCents` 和 `expectedPlanVersion`;价格由服务端收费设置决定。先持久化订单,再调用预下单,返回 `outTradeNo` 与 `payment` 签名参数。
- `GET /api/storageOrderStatus?outTradeNo=...`:仅允许查询本人订单,必要时向微信主动查单并补开通。 - `GET /api/storageOrderStatus?outTradeNo=...`:仅允许查询本人订单,必要时向微信主动查单并补开通。
- `POST https://we.sundynix.cn/api/wechatPayNotify`:无需用户登录,通过微信支付签名校验、APIv3 AES-GCM 解密后核对商户、AppID、付款人、金额和币种;数据库事务提交后返回 204。 - `POST https://we.sundynix.cn/api/wechatPayNotify`:无需用户登录,通过微信支付签名校验、APIv3 AES-GCM 解密后核对商户、AppID、付款人、金额和币种;数据库事务提交后返回 204。
@@ -57,7 +61,7 @@ MinIO 配置读取 `minio` 节点。`past_files` 保存 UUID、size、suffix、c
头像、相册封面、照片、打卡图片和背景使用带外键的文件 ID 字段;日记/记忆日图片使用 `past_record_file` 按 position 保存多图顺序。旧接口的路径字段在数据库中仅保存 ID 镜像,响应时解析为稳定文件访问地址;新请求可直接提交 `fileId`、`avatarFileId`、`coverFileId`、`imageFileIds` 等字段。`past_file_upload` 独立记录每个上传用户,既保留共享去重,也保证权限与容量统计正确。 头像、相册封面、照片、打卡图片和背景使用带外键的文件 ID 字段;日记/记忆日图片使用 `past_record_file` 按 position 保存多图顺序。旧接口的路径字段在数据库中仅保存 ID 镜像,响应时解析为稳定文件访问地址;新请求可直接提交 `fileId`、`avatarFileId`、`coverFileId`、`imageFileIds` 等字段。`past_file_upload` 独立记录每个上传用户,既保留共享去重,也保证权限与容量统计正确。
上传成功返回 `fileId`、`path`、`url`、`file`、`duplicate`。`/api/files/:fileId` 生成短期 MinIO 签名链接,维持原图片的可访问方式,不修改 bucket 的公共访问策略。删除业务关联只做逻辑删除,不删除共享对象。容量检查在内容去重后于事务内执行,同文件不会重复占用同一空间的额度。 上传成功返回 `fileId`、`path`、`url`、`file`、`duplicate`。`/api/files/:fileId` 由后端通过短期 MinIO 签名请求代理读取文件,返回稳定访问地址,并提供图片缓存与 ETag 条件请求,不修改 bucket 的公共访问策略。删除业务关联只做逻辑删除,不删除共享对象。容量检查在内容去重后于事务内执行,同文件不会重复占用同一空间的额度。
后台 **文件管理**(`/backend/admin/files`)通过管理员接口 `/api/adminFiles` 查看全部文件、上传用户、预览、对象路径及元数据,支持关键词、类型、日期筛选和分页。普通用户不能调用文件管理接口。 后台 **文件管理**(`/backend/admin/files`)通过管理员接口 `/api/adminFiles` 查看全部文件、上传用户、预览、对象路径及元数据,支持关键词、类型、日期筛选和分页。普通用户不能调用文件管理接口。
+266 -65
View File
@@ -1,98 +1,299 @@
# PostgreSQL / GORM 数据层(当前版本) # Linux / 宝塔部署文档
数据库为 `192.168.100.127:5432/past-go`,账号 `root`;连接配置见 `config.example.yaml`。 本文是当前部署入口,适用于 PostgreSQL + Redis + MinIO + 微信支付 API v3。以下操作在本地构建后,通过宝塔「文件」上传,再在宝塔「终端」手动执行;不需要配置计划任务,也不要求开发人员拥有 SSH。
复制为本地 `config.yaml` 并填写微信配置。启动时先连接 `postgres` 管理库检查并创建目标库,再执行 GORM AutoMigrate。
也可以只运行迁移:
```sh ## 1. 当前环境与目录
go run ./cmd/migrate -config config.yaml
| 项目 | 当前生产值 |
| --- | --- |
| 系统 / 架构 | Ubuntu 24,Linux amd64 |
| 服务器 | `103.231.12.59` |
| 域名 | `https://we.sundynix.cn` |
| API | `https://we.sundynix.cn/api` |
| 管理端 | `https://we.sundynix.cn/backend/admin/login` |
| 部署目录 | `/home/workspace` |
| systemd 服务 | `past-go.service` |
| 后端监听 | `127.0.0.1:8081`,由 Nginx 代理 |
| PostgreSQL | 服务器本机 `127.0.0.1:5432`,数据库 `past-go` |
| Redis | 服务器本机,具体认证、DB 和前缀以线上配置为准 |
| 文件存储 | MinIO,连接和 bucket 以线上配置为准 |
| Nginx 站点配置目录 | `/www/server/panel/vhost/nginx/` |
服务器目录:
```text
/home/workspace/
├── past-server # Linux 可执行文件,内含管理端静态资源
├── config.yaml # 生产配置,不在 Git 中
├── cert/ # 微信支付私钥、公钥及可选商户证书
├── log/YYYY-MM-DD/ # zap 按日期、级别生成的日志
└── backups/ # 每次更新的旧程序、配置、数据库备份与发布包
``` ```
模型定义在 `internal/model/models.go`,所有模型嵌入 `BaseModel`:`Id string`、`CreatedAt`、`UpdatedAt`、`DeletedAt`。 管理端无需单独部署到 Nginx 网站根目录。上传图片保存在 MinIO,不能通过清理服务器本地文件夹来清理用户文件。
主键与关联 ID 使用 PostgreSQL `uuid` 类型;主键默认 `gen_random_uuid()`,不自增。
表名统一为 `past_` + 单数 snake_case(例如 `User` → `past_user`、`DiaryComment` → `past_diary_comment`);字段按 `UserId` → `user_id` 命名。
启动时会将旧 `past-` 前缀的表无损重命名为 `past_`,保留 UUID、数据和索引。
新增、修改、删除通过 GORM 模型执行;复杂报表通过 GORM Raw 执行,并统一过滤所有关联表及子查询中的 `deleted_at`。 ## 2. 首次拉取与本地开发
删除保留原行及附件;活跃记录的唯一索引带 `WHERE deleted_at IS NULL`,删除后可以重新创建同业务键的记录。
用户对外的六位展示编号是独立业务字段,继续使用数据库序列分配;它不是 UUID 主键。情侣空间编号为 `CP` + 不带连字符的情侣 UUID。
本次创建的是新的 PostgreSQL 库,不会导入旧 MySQL 数据。历史备份如需迁入,需要单独完成数据转换和旧 ID 到 UUID 的关联映射。 本地需要 Git、Go(以 `past-go/go.mod` 的版本为准)、make、Node.js 和 npm。当前管理端 Vite 要求 Node `^20.19.0 || >=22.12.0`;实际依赖以锁文件和安装时提示为准。
验证:`go test ./...`、`go vet ./...`;在设置 `PAST_TEST_POSTGRES_DSN` 后,可运行 `go test ./internal/store -run TestPostgresIntegration -v` 验证真实 PostgreSQL(测试数据全部回滚)。 从仓库根目录执行:
以下保留历史说明,数据库配置与部署步骤以以上内容为准。 ```bash
cd past-go
cp config.dev.example.yaml config.dev.yaml
# 编辑 config.dev.yaml,补齐自己的开发配置,再继续:
make web
make dev
```
--- 首次拉取没有 `web/admin/dist`,必须先执行 `make web`,否则 Go 的 `go:embed` 编译会报资源不存在。`make dev` 构建本机程序并使用 `config.dev.yaml` 启动,默认监听 `:8080`。
# 20261008 原权限兼容与抽烟功能 本地管理端:`http://127.0.0.1:8080/backend/admin/login`。
## 当前行为 开发配置需要填写:
- 日记、相册、记忆日、歌曲和普通打卡恢复原版按情侣成员作者查询;历史 couple_id 不再成为新增过滤条件。未绑定展示方式恢复原版。 - PostgreSQL:地址、端口、数据库、账号密码。启动会检查并创建目标库、执行 GORM AutoMigrate;账号需要对应权限。
- 姨姨继续使用 period_records、period_daily_records、period_sex_records,恢复原版共享记录、来源选择和可见开关。启动不复制或切换姨姨表。此前创建的 personal_period_* 表保留,但本版不读写。 - Redis:地址、认证、DB、`key_prefix`。Redis 是启动依赖,连接失败时后端不会启动。
- 照片响应保持原始 uploads/... 路径,不签名、不改成 /backend/uploads/...;上传静态文件恢复原访问方式,兼容正式版小程序。 - MinIO:endpoint、access/secret key、bucket、SSL 配置;文件通过 `/api/files/:fileId` 访问。
- 抽烟使用独立的 smoking_wallets 和 smoking_entries;消耗一支扣一支、买烟和别人递烟加库存、撤销操作保持事务和幂等。库存随账号保留。 - 微信:AppID、AppSecret、订阅消息模板 ID;AppSecret 只放后端。
- 72 小时解绑冷静期继续保留:双方同意后开始计时,期间可取消,到期解除绑定且保留记录。其他数据权限按原版运行。 - `tencent_map_key`:用于地址解析等地图功能,沿用负责人提供的配置。
- 微信支付:需要联调支付时填写商户配置和证书路径,否则在开发配置中关闭 `wechat_pay.enabled`。
## 部署 模板当前指向团队内网 PostgreSQL,不能将其误当成本机空库。团队需明确开发库和 bucket 的归属;使用独立环境时同时调整数据库、MinIO bucket、Redis DB 或前缀。不要把开发测试账号或配置导入生产环境。
1. 在宝塔备份当前数据库和 uploads,保存原可运行 exe;停止现有 Go 服务。 开发前后可执行:
2. 仅替换 past-server.exe,保留现有 config.yaml、data_dir、uploads、data 和数据库。无需重新配置 Nginx,已正常工作的 uploads 转发继续使用。
3. 启动时补齐抽烟表和冷静期字段;仅迁移旧抽烟库存与流水。smoking_records_v1=done 后不会重复;已经完成 account_records_v1 的环境也不会重新导入库存。不存在姨姨数据迁移。
4. 先验证正式版日记、相册、照片、记忆日、歌曲、普通打卡和姨姨记录,再用新版小程序验证抽烟。
5. 新版小程序的姨姨页面已同步恢复共享方式;抽烟需要上传新版小程序才能显示。
Go 全套和前端回归在本机执行;尚未在生产数据库或微信真机运行本版。历史 binlog 和检查报告显示原记录在库,不应通过清表或倒放日志部署本版。 ```bash
# 当前目录为仓库内的 past-go/
go test ./...
go vet ./...
node --test ../weapp/tests/*.test.cjs
```
以下为 20261005 历史说明,当前部署以以上步骤为准。 真实 PostgreSQL / MinIO 测试是额外集成检查,配置方式见 [后端 README](../README.md)。普通 `go test ./...` 未设置集成环境变量时会跳过这部分测试。
--- ## 3. 生产配置与首次准备
# 20261005 UI 精修与驼峰 API 更新 现有服务器更新直接进入第 4 节,不要重新初始化数据库或覆盖配置。
## 部署顺序 新服务器需准备 PostgreSQL、Redis、Nginx,以及可用的 MinIO bucket。由负责人提供真实生产 `config.yaml` 和支付证书;Git 中只有示例,不能直接用示例覆盖线上文件。
1. 停止现有服务,备份原程序;用新 Windows AMD64 `past-server.exe` 替换程序。保留当前 `config.yaml`、`uploads`、`data` 和数据库。示例配置仅供参考,不要覆盖现有配置。 关键配置:
2. 启动新程序。本次没有新增数据库迁移,保留此前生理期共享功能的数据结构。
3. 如果上一版 `/api`、`/api/` 转发已配置并能访问,这次无需再改 Nginx:驼峰路径继续走同一段转发。附带配置已按你提供的 Nginx 使用 `127.0.0.1:8081`;保留现有 `/backend/` 与 uploads 缓存配置。
4. 检查并重新加载 Nginx,已有配置不变时可以跳过。若调整配置,在你当前 Nginx 机器上检查后重新加载。
5. 浏览器访问 `https://we.sundynix.cn/api` 应返回 API 名称与版本。未登录访问 `/api/coupleInfo` 应返回 401 JSON,不能是 Nginx HTML 404。
6. 管理后台仍从 `/backend/admin/` 进入,新后台已嵌入程序,刷新页面、重新登录后确认 Network 请求为 `/api/adminStats` 等驼峰路径。
7. 微信开发者工具打开包里的 `weapp`;request/uploadFile 合法域名仍为 `https://we.sundynix.cn`。重新编译、真机预览,再上传小程序新版本。
## 接口规则 ```yaml
listen: "127.0.0.1:8081"
data_dir: "/home/workspace"
debug: false
```
- 请求地址:`/api/接口名`,例如 `/api/periodList`、`/api/diaryList?page=1&pageSize=20`。 其他节点按环境填写 `db`、`redis`、`minio`、`wechat`、`wechat_pay` 和地图 key。生产 Redis 使用独立前缀,例如 `past-go:prod:`。
- 小程序、管理后台、上传统一使用新路径;不再附加 GET `_t`。
- 例:`POST /api/periodUpdate`,JSON `{ "id": "314", "cycleLength": 25, "periodLength": 5, "startDate": "2026-09-27", "endDate": "2026-10-01" }`。
- 路径、查询参数、JSON 请求与响应字段统一 lowerCamelCase,例如 `cycleLength`、`periodVisible`、`canAccess`。Multipart 表单字段同样为驼峰。字段值、请求方法和鉴权延续原业务约定。
- 后端及两个客户端在网络边界转换字段名,内部数据库和页面数据模型保持既有结构。旧 PHP 入口与带下划线的旧路径继续兼容。API 响应 `Cache-Control: no-store`;后台请求使用 `cache: no-store`。
- Bearer、上传 token 与后台同源 Cookie 仍有效。上传继续携带兼容 Android 的 token/action 表单项。
- 原 PHP 风格入口继续兼容已发布旧小程序。媒体与后台静态地址仍在 `/backend/` 下。
## 小程序验证 当前 AppID 为 `wxb463820bf36dd5d6`。操作通知和打卡提醒共用模板:
- Android 与 iPhone:标题与微信胶囊不重叠,首屏和底部内容不被遮挡。 ```yaml
- 首页:未绑定显示注册天数和邀请入口,绑定后显示在一起天数;解绑后首页、我的立即按接口更新。 wechat:
- 三个底部入口:首页、记录、我的;详情返回与发布、编辑流程正常。 # appid、secret 使用负责人提供的真实值
- 日记和相册:首次加载、空列表、网络失败分别展示;创建相册与上传照片正常。 notify_template_id: "K_iQMwE_jre0j6QDVL78DZz7wiR1SKVY5h2YJCK6uPU"
- 姨姨:对方可见单独操作;关闭自己的开关不能把自己锁住,权限由 API 判断。双方都有绑定前数据时仍选择唯一记录。 ```
- 改周期、持续天数、开始和结束日期保存后,重新进入展示服务端最新值。
本地已检查 WXML/WXSS 编译、JS 语法、请求/上传 URL 与导航尺寸、Go 测试与管理后台构建;未替代真实微信设备和线上数据库联调。 模板字段为 `thing1`、`time2`、`thing3`;若更换 AppID 或模板,需要同时更新后端配置和 `weapp/utils/subscribe.js`,并在对应小程序后台确认模板存在。
## 本次 UI 精修 微信支付回调应配置为:
小程序首页聚焦双人天数、四个入口和最近记录;记录页分组;日记、相册使用标题旁操作按钮;姨姨选中日期后展开当天操作;个人中心与设置分组。管理后台统一侧栏、页头、统计卡、列表、表格、弹层与登录页,沿用现有组件库。 ```text
https://we.sundynix.cn/api/wechatPayNotify
```
支付证书路径相对于配置文件解析。商户私钥和微信支付公钥需要与配置匹配,`certificate_path` 是可选的商户证书校验配置。
## Redis 与 zap(Linux) systemd 模板在仓库根目录的 [`deploy/linux/past.service`](../../deploy/linux/past.service)。首次部署时复制到 `/etc/systemd/system/past-go.service`,执行:
服务器需安装 Redis 并启用 `redis-server.service`。Redis 仅监听本机 `127.0.0.1:6379` / `::1:6379`,服务配置通过 `redis.addr`、`password`、`db` 和 `key_prefix` 指定。生产前缀为 `past-go:prod:`,避免与开发缓存混用。systemd 服务依赖 PostgreSQL 与 Redis,更新后执行 `systemctl daemon-reload` 和 `systemctl restart past-go`。 ```bash
systemctl daemon-reload
systemctl enable past-go
```
`data_dir: /home/workspace` 时,zap 自动创建 `/home/workspace/log/YYYY-MM-DD/`,按级别记录 JSON 日志,HTTP 访问日志不记录请求正文、认证头或查询参数。保留天数、文件大小、压缩备份数量由 `log` 配置指定。旧 `data/go-server.log` 与 `data/access_token.cache` 不再读写。 服务使用 `www:www` 运行:程序权限 `750 root:www`,配置建议 `600 www:www`;`cert/` 及其私钥必须可被 `www` 读取,运行目录必须允许 `www` 创建日志和临时文件。程序上传并完成配置后,再执行 `systemctl start past-go`。
若 Ubuntu Redis 提示 `libjemalloc.so.2: failed to map segment`,先检查 `ldd /usr/bin/redis-server`:当前服务器的 `/usr/local/lib` 中有同名库,通过 Redis 的 systemd drop-in 设置 `Environment=LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu` 使用系统自带库,保留原有 `NoExecPaths` 等沙箱限制。 新数据库会初始化管理员 `past / past`;已有数据库正常启动不会重置管理员密码。
已有管理员可通过 `past-server -config config.yaml -reset-admin` 显式重置为 `past / past`;新数据库也使用该默认账号。普通启动不会重置密码。 ## 4. 本地生成 Linux 发布包
以下命令从仓库根目录开始。默认目标是当前生产 Linux amd64;不要将 macOS 本机构建的程序上传到 Linux。
```bash
cd past-go
past_version="$(date +%Y%m%d-%H%M%S)-$(git rev-parse --short HEAD)"
# 重新构建管理端并嵌入后端,避免后台静态资源仍是旧版。
make all GOOS=linux GOARCH=amd64 VERSION="$past_version"
go test ./...
go vet ./...
node --test ../weapp/tests/*.test.cjs
past_package="dist/releases/$past_version"
mkdir -p "$past_package"
cp dist/past-server-linux-amd64 "$past_package/past-server"
printf '%s\n' "$past_version" > "$past_package/VERSION"
(cd "$past_package" && shasum -a 256 past-server > SHA256SUMS)
tar -czf dist/past-release.tar.gz -C "$past_package" \
past-server VERSION SHA256SUMS
```
产物:`past-go/dist/past-release.tar.gz`。建议提交代码后打包,使版本号中的提交 ID 可以追溯;发布时记录是否含未提交改动。
只修改后端或管理端,需要更新服务器二进制;只修改小程序页面,则重新编译、上传小程序即可。涉及接口变更时,先部署兼容的新后端,再上传小程序。
## 5. 宝塔上传与更新现有服务器
在宝塔「文件」进入 `/home/workspace`,上传上一节生成的 `past-release.tar.gz`。先确认上传成功,再进入宝塔「终端」。
下面的命令**仅适用于第 4 节生成的发布包格式**,不要直接用于历史 `past-server.new + manifest.json` 发布包。数据库参数应与服务器现有 `config.yaml` 一致;命令会交互询问数据库密码,不会改动线上配置、证书或已有业务数据。
在宝塔终端整段粘贴执行:
```bash
bash <<'DEPLOY'
set -euo pipefail
umask 077
cd /home/workspace
# 根据现有 config.yaml 核对这四项。
past_db_host=127.0.0.1
past_db_port=5432
past_db_name=past-go
past_db_user=root
test -f past-release.tar.gz
test -f past-server
test -f config.yaml
mkdir -p backups
past_backup=$(mktemp -d /home/workspace/backups/release-XXXXXX)
mkdir "$past_backup/release"
cp -a past-server "$past_backup/past-server.before"
cp -a config.yaml "$past_backup/config.before.yaml"
read -r -s -p 'PostgreSQL password: ' past_db_password < /dev/tty
printf '\n'
PGPASSWORD="$past_db_password" pg_dump \
-h "$past_db_host" -p "$past_db_port" -U "$past_db_user" \
-d "$past_db_name" -Fc --no-owner --no-acl \
-f "$past_backup/database.before.dump"
unset past_db_password
tar -xzf past-release.tar.gz -C "$past_backup/release" \
past-server VERSION SHA256SUMS
(cd "$past_backup/release" && sha256sum -c SHA256SUMS)
past_version=$(cat "$past_backup/release/VERSION")
install -o root -g www -m 750 \
"$past_backup/release/past-server" ./past-server.next
past_switched=0
rollback() {
past_status=$?
if [ "$past_switched" = 1 ]; then
echo '部署失败,恢复原程序'
systemctl stop past-go || true
cp -a "$past_backup/past-server.before" ./past-server.next
mv -f ./past-server.next ./past-server
systemctl start past-go || true
fi
exit "$past_status"
}
trap rollback EXIT
past_switched=1
systemctl stop past-go
mv -f ./past-server.next ./past-server
systemctl start past-go
past_ready=0
for attempt in $(seq 1 40); do
if curl -fsS --max-time 2 http://127.0.0.1:8081/healthz | grep -qx 'ok'; then
past_ready=1
break
fi
sleep 1
done
test "$past_ready" = 1
./past-server -version | grep -Fx "past-server $past_version"
systemctl is-active --quiet past-go
past_switched=0
mv past-release.tar.gz "$past_backup/"
echo "部署成功:$past_version"
echo "备份目录:$past_backup"
systemctl is-active past-go
DEPLOY
```
出现 `部署成功` 和 `active` 才表示本机启动检查通过。启动等待期间短暂出现 `curl: (7)` 是轮询结果;若最终失败,应检查错误和服务日志,不能只凭文件已上传就判断部署完成。
该命令备份 PostgreSQL 的一致性快照,并在更新失败时恢复旧程序。**不会自动回滚数据库迁移**;涉及不兼容表结构变更的版本,需单独制定数据库迁移、停写和恢复方案。不要在上线失败后直接覆盖或恢复正在写入的生产数据库。
## 6. 上线验证与排查
```bash
/home/workspace/past-server -version
systemctl status past-go --no-pager
curl -fsS http://127.0.0.1:8081/healthz
curl -fsS https://we.sundynix.cn/healthz
curl -I https://we.sundynix.cn/
journalctl -u past-go -n 100 --no-pager
```
核对以下功能:
- 公网 `/healthz` 返回 `ok`,根路径跳转管理端登录页。
- 管理员可登录,公告、存储套餐和文件列表能正常加载。
- 已绑定用户的记录功能正常;未绑定用户点击记录、更多、存储入口会提示邀请绑定,后端记录接口返回绑定权限错误。
- 图片能访问;稳定文件地址 `/api/files/:fileId` 保留缓存与条件请求能力。
- 打卡页能读取账号保存的抽烟显示开关,位置在「我的 → 更多」。
- 涉及支付改动时,用负责人指定的测试套餐和真实微信用户验证支付回调、主动查单与权益到账;不要依靠前端支付成功提示判断入账。
启动失败优先检查 PostgreSQL、Redis、MinIO、支付证书路径与文件权限。业务日志在 `/home/workspace/log/YYYY-MM-DD/`;`journalctl` 可看到服务启动阶段的错误。
Nginx 只有在域名、监听端口或代理规则变化时才需调整。通过宝塔「文件」编辑 `/www/server/panel/vhost/nginx/` 内实际站点配置,保留 SSL 和证书续签配置,不在网站表单中覆盖整份配置。代理规则参考 [`deploy/linux/nginx-past.conf`](../../deploy/linux/nginx-past.conf)。修改后执行:
```bash
/www/server/nginx/sbin/nginx -t
# 只有上一条检查成功后,才执行:
/www/server/nginx/sbin/nginx -s reload
```
## 7. 手动回滚程序
选择本次更新输出的真实备份目录。确认本版数据库仍兼容旧程序后,在宝塔终端执行:
```bash
past_backup='/home/workspace/backups/替换为实际备份目录'
test -f "$past_backup/past-server.before" && \
install -o root -g www -m 750 \
"$past_backup/past-server.before" /home/workspace/past-server.rollback && \
systemctl stop past-go && \
mv -f /home/workspace/past-server.rollback /home/workspace/past-server && \
systemctl start past-go
systemctl status past-go --no-pager
curl -fsS http://127.0.0.1:8081/healthz
```
备份中的 `config.before.yaml` 和 `database.before.dump` 留作必要时人工恢复,不在程序回滚时默认覆盖配置或数据库。
## 8. 小程序发布
微信开发者工具打开仓库内 `weapp/`。`weapp/config/env.js` 仅导出 `API_BASE`,不会自动区分开发版、体验版和正式版:
```js
// 本地开发或真机联调:填写开发机地址。
const API_BASE = 'http://192.168.100.3:8080/api';
module.exports = { API_BASE };
```
上传体验版或正式版前,将这一行改为:
```js
const API_BASE = 'https://we.sundynix.cn/api';
```
重新编译,确认小程序 AppID、接口地址和隐私协议配置,真机验证后再上传。在微信后台配置正式 request / uploadFile / downloadFile 合法域名 `https://we.sundynix.cn`;若某功能直接访问其他域名的对象或外部图片,需要同时核对该实际域名的配置。
每次发布同时记录后端版本、小程序版本和验证结果,避免协同开发时把本地测试地址随代码上传到正式版。