# NAS + Gitea 部署文档 ## 概述 岩美酒库管理系统使用 **群晖 NAS 上自托管的 Gitea(Forgejo)** 作为代码仓库和 CI/CD 平台。代码推送到 `main` 分支后,NAS 上的 Gitea Runner 自动构建并部署到 EC2 服务器。 --- ## 服务地址 | 服务 | 地址 | |------|------| | Gitea Web UI | `https://git.51yanmei.com` | | Gitea SSH | `ssh://git@git.51yanmei.com:2222` | | Actions 面板 | `https://git.51yanmei.com/wangjia/jiu/actions` | | 线上应用 | `https://jiu.51yanmei.com` | | 管理端 Web | `https://jiu.51yanmei.com/app/` | --- ## Gitea Runner 说明 Runner 实际运行在**本机 Mac**(不是 NAS),通过 LaunchAgent 开机自启,连接 NAS 上的 Forgejo。 ### 本机文件布局 | 文件 | 说明 | |------|------| | `/Users/wangjia/bin/act_runner` | act_runner 二进制(v0.2.11) | | `/Users/wangjia/bin/act_runner_start.sh` | 启动脚本(含 TCP 中继逻辑) | | `/Users/wangjia/bin/tcp_relay.py` | Python3 TCP 中继(旧内网方案,现已通过域名直连) | | `/Users/wangjia/.act_runner` | Runner 注册信息 | | `/Users/wangjia/.act_runner_config.yaml` | Runner 配置(label: `mac:host`,capacity: 1) | | `~/Library/LaunchAgents/com.jiu.act-runner.plist` | LaunchAgent plist,开机自启 | | `/tmp/act_runner.log` | 运行日志 | ### Workflow 标签 `.gitea/workflows/deploy-{client,site,server}.yml` 中使用 `runs-on: mac`,对应 runner label `mac:host`。 ### 检查 Runner 状态 ```bash # 查看日志 tail -f /tmp/act_runner.log # 确认进程在跑 ps aux | grep act_runner | grep -v grep # 手动重启(LaunchAgent 会自动重启,一般不需要) kill $(pgrep -f act_runner_start.sh) ``` ### Runner 不工作时的排查步骤 1. **确认 Gitea 可达**:`curl -sf https://git.51yanmei.com/api/v1/version` 2. **查看最近日志**:`tail -30 /tmp/act_runner.log` 3. **手动测试**:`/Users/wangjia/bin/act_runner daemon --config ~/.act_runner_config.yaml`(从终端运行应直接成功) 4. **强制重启**:`kill $(pgrep -f act_runner_start.sh)` — LaunchAgent 会在几秒内自动重拉 ### 重新注册 Runner(token 失效时) ```bash # 1. 停止当前 runner kill $(pgrep -f act_runner_start.sh) # 2. 删除旧注册文件 rm ~/.act_runner # 3. 在 Forgejo 获取新 token: # Settings → Actions → Runners → Create Runner Token # 4. 注册(从终端运行,不要从 LaunchAgent) /Users/wangjia/bin/act_runner register \ --no-interactive \ --instance https://git.51yanmei.com \ # SSH remote: ssh://git@git.51yanmei.com:2222/wangjia/jiu.git --token <新token> \ --name mac-runner \ --labels mac:host # 5. 重启(LaunchAgent 自动接管) kill $(pgrep -f act_runner_start.sh) ``` --- ## Workflows 仓库根目录 `.gitea/workflows/` 下有三个 workflow 文件: ### `deploy-{client,site,server}.yml` — 三条独立部署流程 发版已拆成三条互不影响的流水线,按 tag 前缀触发: | workflow | 触发 tag | 范围 | |----------|---------|------| | `deploy-client.yml` | `client-v*.*.*` | Flutter 全平台 + version.yaml | | `deploy-site.yml` | `site-v*.*.*` | Eleventy 营销站 | | `deploy-server.yml` | `server-v*.*.*` | Go 后端 + nginx | **步骤(各自):** `compile-*.sh` 编译打包 → `test.sh ` 门禁 → `release-.sh` 创建 Forgejo Release → `deploy-.sh` SSH 到 EC2 部署 → Telegram 通知。公共函数在 `scripts/ci/lib-forgejo.sh`。 ### `manual.yml` — 手动部署 / 回滚 **触发条件:** Forgejo UI 手动触发(workflow_dispatch),输入带前缀 tag(如 `client-v1.0.55`),按前缀路由到对应 `deploy-.sh` **步骤:** 只运行 `deploy.sh`,从 Forgejo Release 下载已有产物直接部署,跳过编译和测试。 ### `ci.yml` — PR 测试流程 **触发条件:** 非 `main` 分支的 push 或 PR **步骤:** 只跑测试(`go test` + `flutter test`),不构建不部署。 --- ## Secrets 配置 在 Gitea 仓库的 **Settings → Secrets** 中配置以下密钥: | Secret 名称 | 用途 | |-------------|------| | `EC2_SSH_KEY` | EC2 服务器的 SSH 私钥(PEM 格式,完整内容) | | `EC2_HOST` | EC2 服务器 IP 或域名 | | `EC2_USER` | EC2 SSH 用户名(如 `ec2-user`、`ubuntu`) | | `FORGEJO_TOKEN` | Gitea 个人访问 Token(用于创建 Release、下载 asset) | | `FORGEJO_URL` | Gitea 地址:`https://git.51yanmei.com` | | `TELEGRAM_TOKEN` | Telegram Bot Token(部署通知) | | `TELEGRAM_CHAT_ID` | Telegram Chat ID(接收通知的对话) | --- ## 触发部署方式 ```bash # 开发完成,确认测试通过后打 tag git tag -a v1.1.0 -m "v1.1.0" git push nas main && git push nas v1.1.0 # → CI 自动:compile → test → release → deploy → Telegram 通知 ``` **回滚:** Forgejo UI → Actions → Manual Deploy → 输入旧 tag → Run --- ## EC2 服务器目录结构 ``` /opt/jiu/ ├── backend/ │ ├── jiu-server # Go 可执行文件 │ └── config/ │ └── version.yaml # 版本信息(由 CI 自动更新) ├── web/ # Flutter Web 构建产物(/app/ 路径) ├── marketing/ # 营销站点静态 HTML │ ├── assets/ │ ├── index.html │ ├── docs.html │ └── download.html ├── images/ # 商品图片上传目录 └── web-old/ # 上一版本 Flutter Web(回滚备用) ``` Systemd 服务名:`jiu` 日志:`journalctl -u jiu -f` --- ## Nginx 路由说明 配置文件:`deploy/nginx-jiu.conf`(CI 部署时自动更新) | 路径 | 服务 | |------|------| | `/api/*`, `/health`, `/version` | Go 后端 API | | `/images/*` | 商品图片静态文件 | | `/app/` | Flutter 管理端 SPA | | `/product/` | 商品扫码公开页(Flutter Web 路由) | | `/` | 营销首页 |