Files
blog/架构总览.md
T
zqlit 5f27ad321d chore(备份): 异地备份定案为 OpenList 离线 bundle,撤销全部 git 辅仓
用户定案:「辅助仓就用 openlist,其他不再考虑」。
据此把前一轮为 Gitee 铺的路全部收回,git 远端只剩 CNB 一个。

一、git 配置收口
- `pushall` 别名 `origin + gitee` → `!git push origin main`(只推唯一远端)
- 移除 `gitea` remote(自建 23.254.236.47:3001)—— 远端仓库本身没删,
  需要时可 `git remote add` 恢复;改动前配置存
  `.workbuddy-backup/git-remotes.20261006-211516.txt`
- 确认无 gitee 相关 credential 残留

二、发布链路去 Gitee 化(6 处)
- `deploy/editor-api/bootstrap.sh`
    · 删掉 GITEE_URL / GITEE_SSH_KEY 两个变量与「没给私钥就降级」的分支
    · PUSH_REMOTES 默认 → origin
    · 原「配 gitee 辅仓远端」一节改为「清理退役远端」循环(gh/gitee/gitea),
      让从旧部署续用的工作区自动恢复干净
- `docker-compose.editor.yml`、`editor-api/server.mjs` → 默认值 origin
- `editor-api/README.md` → 变量表同步
- `editor-api/Dockerfile` → 注释里的「CNB / GitHub」改「CNB」
- `blog-admin/src/routes/rss/tools.ts` → deploy-notify 的注释里
  「与 Gitea Actions 的构建通知配套」改为中性描述
  (该轮询链路 2026-10-04 起已被 CNB 国内节点直传取代)

三、`scripts/setup-cnb-remotes.sh` 重写为单远端模式
- 去掉 GITEE_URL / GITEE_TOKEN 参数、校验、凭据写入与自检提示
- 新增「清理退役远端」步骤
- 凭据处理改为「已存在空的 credential.helper 就不再添加」,
  不再用 --replace-all —— 本仓另有一个从 `$HOME/.workbuddy/secrets/cnb-token`
  读令牌的自定义 helper,那是有效的,不能被脚本抹掉

四、备份升级为「唯一辅仓」的配置
- 保留份数 3 → 7(一周窗口;每份 605.5 MB ≈ 4.2 GB,F50 有 256 GB)
    · `scripts/backup-task.cmd` 默认参数 --keep 7
    · `scripts/backup-bundle.mjs` 的 KEEP 默认值同步为 7
      (原先写的是 2,一直被命令行参数掩盖着)
- 远端目录 `/本地/备份` → `/本地/备份/blog-bundle`:
  根目录是用户自己在用的(放着 github-zqlit-*、local-repos-* 等手工备份),
  实测发现直接放根下的 bundle 已被清掉 —— 改子目录隔离,避免混放与误删

五、新增 `scripts/backup-run.mjs`:备份的推荐入口 + 失败告警
- 读 `.workbuddy-backup/openlist-backup.env`(只补空缺,环境变量优先)
- 跑 backup-bundle.mjs 并实时透传输出,同时留一份日志尾部
- 退出码非 0 → 经 `scripts/send_mail.js` 发告警邮件(附日志尾部与常见原因);
  成功默认不发,`--notify-success` 才发
- 退出用 `process.exitCode` 而非 `process.exit()`,避免截断未排干的 stdout
- 发信失败不改判备份退出码 —— 通知不该掩盖真正的故障
- 理由:这是当前**唯一**的异地备份,而「每天自动跑」的任务最典型的失败模式
  恰恰是静默的(F50 被带出门、换了网段、OpenList 没起来、口令改过……),
  没有告警就要等到真要用备份那天才发现
- `scripts/backup-task.cmd` 改调它

六、文档
- `架构总览.md`
    · §1.2 地址地图:备份行改指 F50/OpenList;通知行补「兼做备份失败告警」
    · §2 旅程图:双推改单推,并说明备份换了介质
    · §5.1 / §5.2 推送与远端:只剩 origin;补「已移除远端」表与恢复命令;
      GitHub 退役记录保留并补上「CI 定义也已删除」
    · §5.3 由「辅仓选型」改为「异地备份的定案」—— 明确不走 git 远端;
      平台对比数据保留备查,并注明 `bin/linux/hugo` 出库不必再做了
    · §5.6 补「唯一备份」定位、专属子目录、失败告警、keep 7、SMTP 配置键,
      实测数据更新为本次复测值
    · §6 待办:#2 定案、#3 不必做、#4 已移除、#8 已更新、#10 定位升级,
      新增 #11(F50 目录使用约定)
- `CNB构建落地方案.md` §4.0:双远端改单远端,脚本示例去掉 Gitee 参数
- `README.md`:推送说明改单推;脚本表补 backup-run.mjs

实测(2026-10-06,本轮复测):
  bundle 7.4s / AES-256-GCM 加密 1.3s / 上传 19.2s(31.6 MB/s)
  / 读回 sha256 一致 → 端到端 60.6s,退出码 0
  告警邮件链路已实测(发出一封「备份成功」验证信)

★ 一处过程记录,供以后避免重复踩坑:
  中途我把「本机沙箱里 `env -u ... cmd > file` 会让输出整个消失」
  误判成 process.exit 截断 stdout,并据此改了日志实现;
  随后用 `env -u FOO echo hi > file`(同样零输出)证伪 ——
  那是沙箱文件重定向的伪影,与脚本无关。相关改动已回滚,
  只留下本身无害的 process.exitCode 写法。
2026-10-06 21:27:28 +08:00

22 KiB
Raw Blame History

优世界博客 · 架构总览

更新时间:2026-10-04(CNB 迁移完成当日) 状态:迁移已落地并跑通(四线路全绿,单次发布约 3.5 分钟) 本文档只描述现状;迁移前的复杂度审计与选型过程见文末「相关文档」。


0. 一句话

四个子系统,一条 3 步的托管发布链路。构建与发布已从「自建 Gitea + act_runner + 广州中转机」迁到 腾讯云 CNB(cnb.cool) —— 需要自己运维的机器从 3 台降到 0 台。


1. 全景

1.1 四个子系统

# 子系统 技术栈 跑在哪 状态
1 内容系统 Hugo 0.128.2 extended + Ying 主题,138 篇 md;产物约 3200 文件 / 424MB 产物分发到 3 个 CDN 正常
2 评论系统 blog-admin/ = artalk-cf(Artalk v2 兼容服务端)+ RSS 机器人 Cloudflare Workers + D1 + KV → api.200181.xyz ✅ 零服务器零运维
3 写作系统 write-server/(Next.js 16,post.usj.cc)
write/(本地 Windows 前端)
独立 Docker 主机/本机 可用(两套前端功能重叠)
4 发布基础设施 CNB 流水线(.cnb.yml)+ 又拍云 + 多吉云 + EdgeOne 腾讯云 CNB(托管) 新建,已跑通

1.2 服务与地址地图

角色 地址 / 位置 说明
代码主仓 cnb.cool/zqlit/blog CNB,私有;构建由它触发;唯一 git 远端
异地备份 中兴 F50 上的 OpenList(/本地/备份/blog-bundle/) 整仓加密 bundle,计划任务每天 03:30 自动跑,不依赖任何 git 平台(见 §5.6)
构建 + 发布 CNB 流水线(腾讯云国内节点,4 核 8G) 托管,0 元(免费额度内)
密钥仓库 cnb.cool/zqlit/blog-secrets CNB「密钥仓库」类型,10 项变量经 imports 注入
境内源站 又拍云对象存储 由 CNB 国内节点直传(原为 if: false 的死代码)
国内加速 多吉云 CDN 回源又拍云
境外线路 EdgeOne Pages(项目 hugo-blog,--area overseas) 腾讯 EdgeOne 国际站
评论后端 api.200181.xyz Cloudflare Workers
通知 QQ 邮件(imql@qq.com) 已收敛为单一通道;同时承担备份失败告警(§5.6)

关键点:境内、境外仍是两条独立线路,但由同一条流水线一次推完 —— 这是本次迁移最大的结构性改善。


2. 一次发布的完整旅程(3 步)

① 写作        write-server(网页) 或  write/(本地 Windows)
       │
② git push      git push origin main      (别名 git pushall,同一件事)
       │        └─ origin → cnb.cool/zqlit/blog   (**唯一远端**,触发构建)
       │           ★ 异地备份不走 git 远端 —— 由本机计划任务每天 03:30
       │             跑整仓加密 bundle 传到 F50 上的 OpenList(§5.6)
       ▼
③ CNB 流水线(国内节点,约 3.5 分钟,7 个 stage 顺序执行)
       ├─ 1. Hugo 构建          草稿隐藏预处理 → hugo --minify --gc → 算构建哈希
       ├─ 2. 同步到又拍云        upx sync(境内直传,非阻断但如实上报)
       ├─ 3. 刷新又拍云 CDN      purge 首页 + sitemap/rss/archives/posts 等固定入口
       ├─ 4. 刷新多吉云 CDN      node scripts/refresh_cdn.js
       ├─ 5. 部署 EdgeOne        edgeone pages deploy --area overseas
       ├─ 6. 上报部署状态        POST api.200181.xyz/api/deploy-status
       └─ 7. 邮件通知            成功 → stages 末尾;失败 → failStages

对照:迁移前是 7 步,中间有 3 个环节是你自己运维的服务器。


3. 流水线细节(.cnb.yml,284 行)

触发 条件 说明
push 推送到 main 主链路
crontab 0 9 * * *(Asia/Shanghai) 每天 09:00,与 push 共用同一组 stage(YAML 锚点)
机制 实现
构建镜像 deploy/Dockerfile,hugo 二进制随仓库携带(bin/linux/hugo,linux/amd64)
⚠️ docker 上下文 by: [bin/linux/hugo] —— CNB 的 docker build 只看得见 Dockerfile + by 列出的文件,漏写会报 not found
密钥注入 imports: https://cnb.cool/zqlit/blog-secrets/-/blob/main/secrets.yml
stage 间传状态 落盘 .ci_status(原版靠 needs.*.outputs)
并发控制 lock.cancel-in-progress(对应原 concurrency)
非阻断 又拍云三步 + 状态上报 + 邮件用 allowFailure: true,失败仍写状态如实上报
资源 cpus: 4(4 核 8G)

4. 迁移前后对比

维度 迁移前(Gitea 自建) 迁移后(CNB)
发布链路环节 7 步 3 步
自维护机器 / 服务 3 台(Gitea 主机 + act_runner + 广州中转机) 0(构建托管)
流水线定义 GitHub Actions 1169 行 .cnb.yml 284 行
产物传递 打 tar.zst → artifact → 中转机跨境下载 同一 pipeline 共享工作目录,无需传递
又拍云直传 if: false(境外 runner 必挂,从未跑通) 已跑通(国内节点直传)
COS 中转层 需要(存储 + 流量账单) 已砍
github.server_url 兼容分支 8 处 0
通知 3 套(TG / 飞书 / 邮件),约 400 行 1 套(邮件)
图片优化 + 反向 commit CI 内每轮白跑(15 张老图处理不掉) 未迁(如需保留,照搬 scripts/optimize_images.js)
构建环境 境外 VPS 腾讯云国内节点 4 核 8G
费用 VPS 月租 0 元(100GiB 仓库 + 160 核时/月)
单次发布耗时 — 约 3.5 分钟

原链路里那些补丁(COS 中转 / sync.sh 每分钟轮询 / artifact 打包 / 兼容分支) 唯一根因是「runner 在境外」。CNB 节点在国内,这一整层随之消失。


5. 运维要点

5.1 推送

git push origin main     # 推 CNB(触发构建)
git pushall              # 完全等价 —— 它只是个别名,本仓只有这一个远端

本仓只有 origin 一个 git 远端。 曾经的双推(git push origin main; git push gh main) 随 GitHub 退役而取消;后来一度改写成 origin + gitee,也随「异地备份改用 OpenList」 (§5.6)一并取消 —— 备份换了介质,就不再需要第二个 git 远端。

留着的两条教训:

  • 不要用「一个 remote 挂多个 pushurl」 —— 实测 git 是「顺序推、遇错即停」, 第一个失败后面的都不推,备份意义就没了。真要加辅仓,得用「独立 remote + 别名」。
  • 别名当初写成 ; 串联而非 &&,正是为了让一段失败不影响另一段。现在只有一个远端, 这层考虑自然消失。

5.2 远端

remote 地址 角色
origin https://cnb.cool/zqlit/blog.git 唯一远端(fetch + push,触发 CNB 构建)

已移除的远端(改动前的完整配置快照留在 .workbuddy-backup/git-remotes.*.txt):

remote 地址 移除于 原因
gh github.com/zqlit/blog 2026-10-06 账号被标记、仓库被按 AUP 清空(见下)
gitee (从未真正建立过) 2026-10-06 两条硬门槛过不去,改走 OpenList 离线备份(§5.3)
gitea 自建 23.254.236.47:3001 2026-10-06 发布链路早已不依赖;留着只会在推送时撞上落后 56 个提交的旧副本

远端仓库本身都没删,只是本地不再挂。 想临时恢复自建 Gitea 副本:

git remote add gitea http://<用户名>:<密码>@23.254.236.47:3001/zqlit/blog.git
git push gitea main

⚠️ GitHub 退役记录(2026-10-06)

起因:GitHub 账号被平台标记,随后仓库被按 AUP 合规条款清空 —— 远端留下一条孤立提交(无父提交):

c21d5669 2026-10-06 20:08:32 +0800 zqlit <zqlit@users.noreply.github.com>
chore: remove repository content (AUP compliance)

同时远端 main 的历史与本地完全分叉(两边只共享 2024-07-11 的 Initial commit, 之后每个提交 SHA 都不同;远端那份是 989 提交、剥离了 .env/私钥/大二进制的变体)。 教训:别把「备份」寄托在会对内容做合规处置的平台上; 且一旦某次历史被重写,SHA 从此再也对不上。

本项目随后清掉了 GitHub 的全部痕迹:remote、推送别名、发布链路里 4 处硬编码 (bootstrap.sh / docker-compose.editor.yml / server.mjs / README.md)、 以及 CI 定义本身(整个 .github/ 目录,1268 行)。

5.3 异地备份的定案(2026-10-06)

结论:异地备份不走 git 远端 —— 改用整仓加密 bundle → OpenList(见 §5.6)。

一句话理由:备份要防的是「平台整体出问题」,而把副本放到另一家同样性质的平台上, 只是把鸡蛋从左边口袋挪到右边口袋。真正的第三层得换介质。

下面这些实测数据保留下来 —— 下次再冒出「要不要加个 git 辅仓」的念头时, 这几张表就是答案。

体积分布(HEAD,实测 457.4 MB / 2509 文件):

目录 体积 说明
content/(含 posts/) ≈ 308 MB 博客正文与媒体(mp4/mp3/大图),搬不走
bin/linux/hugo 83.1 MB CNB 构建用的 hugo 二进制,可移出 git
static/ ≈ 38 MB 站点静态资源
themes/ 20.3 MB Ying 主题
其余全部 ≈ 8 MB 代码、文档、脚本

Gitee 的两条硬约束 —— 都不满足:

约束 Gitee 免费版 本仓库当前 判定
单仓库容量 ≤ 500 MB .git 620 MB ❌ 超 24%
单文件大小 ≤ 50 MB bin/linux/hugo 83.1 MB ❌ 必删
用户总仓库容量 5 GB 620 MB ✅
私有仓协作人数 5 人 个人 ✅ 无关

bin/linux/hugo 是硬门槛:不管怎么瘦身历史,只要它还跟踪在 HEAD 里,Gitee 一律拒收。 → 移出后 HEAD ≈ 374 MB,才有一份余量。

对照:阿里云效 Codeup 基础版 —— 两条硬约束一条都不存在:

项 Gitee 免费版 云效 Codeup 基础版
单库容量 ≤ 500 MB Git 5 GiB + LFS 5 GiB
单文件 ≤ 50 MB Web 50 MB / 命令行 200 MB
620 MB 的 .git 超 24%,推不上 占 12.1% ✅
83.1 MB 的 hugo 超 66%,一律拒收 占 41.6% ✅
价格 免费 0 元/人/年,不限人数、不限仓库数

→ 若选 Codeup,bin/linux/hugo 不必出库,deploy/Dockerfile 与 .cnb.yml 的 by: 字段一行都不用改(首推 620 MB 也在其 60 分钟推送超时内)。 注意两点:① 默认「中心组织」只支持阿里云 RAM 账号登录、且必须绑钉钉, 不接受的可选 2025-12 上线的「地域组织」(华东2上海,支持自建账号密码); ② 基础版无「删库保护」,容量到 90% 提醒、超限直接禁止写操作(连删文件都做不了)。 已有的阿里云 OSS AccessKey 不能用来建 Codeup 仓库 —— git 推送走独立的克隆账号密码或 SSH Key。

★ 这些都只是「换一个篮子」,不是容灾。 CNB 与 Gitee/Codeup 同属国内大区;GitHub/GitLab 又执行同一套合规逻辑 (本轮 GitHub 被按 AUP 清空即为例证)。 所以最终一个 git 辅仓都没有采用 —— 改用不依赖任何平台账号的离线备份:见 §5.6。

顺带一个副作用:bin/linux/hugo「出库」这件事不用做了。 那个 83.1 MB 二进制之所以成为问题,只因为它卡在 Gitee 的单文件 50 MB 上限上。 既然不走 Gitee,deploy/Dockerfile 的取 hugo 方式与 .cnb.yml 的 by: 字段 一行都不用改。

5.4 凭据

  • 令牌存仓库外:~/.workbuddy/secrets/cnb-token
  • 本仓 credential.helper 指向一个自定义脚本;.git/config 无明文
  • ⚠️ 本机全局 helper 是 GCM(会弹窗、对第三方 HTTPS 远端还会挂死);wincred 对 cnb.cool 有过「幽灵记录」删不掉 → 故用自定义 helper 绕开

5.5 密钥

  • 修改密钥 → 编辑 CNB 密钥仓库的 secrets.yml(网页编辑,禁 clone)
  • 本地 cnb-secrets.yml 只是粘贴草稿(已 gitignore,不入库)
  • ⚠️ CNB 的 imports 是一层映射(key 就是变量名本身);又拍云服务名在 CNB 里必须叫 UPYUN_SERVICE(旧 Gitea 里叫 UPYUN_BUCKET,照抄会「变量未定义」)

5.6 整仓离线备份(中兴 F50 / OpenList)★ 当前唯一的异地备份

定位:2026-10-06 起这一层就是本项目的异地备份本体 —— 不再有任何 git 辅仓(§5.3)。 所以它的可靠性与失败可见性都比以前更重要:它一旦悄悄失效,代码就只剩 CNB 一处。 失败告警因此是必备件,不是加分项。

目标介质:中兴 F50 5G CPE 内置 256 GB 存储,上面跑 OpenList (http://192.168.0.1:5244,WebDAV 端点必须带 /dav 前缀)。7×24 常开、走局域网、 不依赖任何 git 平台账号 —— 这是它比「再选一个代码托管平台」更值钱的地方。

存放位置:/本地/备份/blog-bundle/ —— 专属子目录,不是 /本地/备份/ 根下。 根目录由用户自己在用(放着 github-zqlit-*、local-repos-* 等手工备份), 把文件混进去既容易被误删,也让「清理旧份」多一层风险。 (早期版本确实直接写在根目录下,实测发现文件已被清掉,故改为子目录隔离。)

为什么是 bundle 而不是直接推 git:WebDAV 不支持原子的 rename/lock, 把 bare repo 挂上去直接 git push 会让对象写坏 —— 表面成功、实际随机损坏, 可能几个月后才发现。bundle 是单文件顺序写,没有这个问题。

为什么加密:本仓库历史里含 .env、TLS 私钥、GITEA_SECRETS.md。 介质是一台随身设备的内部存储,明文等于把密钥放在可能丢失 / 刷机 / 送修的设备上。 OpenList 的登录只保护访问通道,不保护存储介质 —— F50 丢了拆开就能读。

为什么不用 gpg:本机 gpg 2.4.9 在 Windows 下已损坏(反复 removing stale lockfile, node spawn 直接 EBUSY)。改用 Node 内置 crypto 的 AES-256-GCM: 零外部依赖、带认证标签(能检测篡改/截断)、可流式处理 600 MB 不爆内存。

加密文件布局:magic(8) | salt(16) | iv(12) | 密文(...) | GCM tag(16), 密钥由 scrypt(N=32768, r=8, p=1) 从口令派生。

用法(scripts/backup-bundle.mjs,零 npm 依赖):

# 推荐入口:带失败告警的包装器(计划任务用的就是它)
node scripts/backup-run.mjs                          # = backup-bundle 的默认参数
node scripts/backup-run.mjs --verify --keep 7        # 计划任务的默认组合
node scripts/backup-run.mjs --dry --notify-success   # 试跑并强制发一封成功邮件

# 底层脚本(backup-run.mjs 就是转发到它)
node scripts/backup-bundle.mjs                 # 加密 + 上传 + 比对字节数
node scripts/backup-bundle.mjs --verify        # 额外下载回来比对 sha256(端到端最可靠)
node scripts/backup-bundle.mjs --dry           # 只打包加密,不上传
node scripts/backup-bundle.mjs --keep 7        # 远端保留最近 7 份(默认值)
node scripts/backup-bundle.mjs --list          # 列出远端现有备份
node scripts/backup-bundle.mjs --decrypt <文件> [--out x.bundle]   # 恢复用

配置(按序查找,先找到生效):环境变量 → ~/.openlist-backup.env → .workbuddy-backup/openlist-backup.env(已在 .gitignore 内)。

键 用途
OPENLIST_URL / OPENLIST_USER / OPENLIST_PASS OpenList 地址与账号
OPENLIST_DIR 远端目录,当前 /本地/备份/blog-bundle
BACKUP_PASSPHRASE bundle 加密口令
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_TO 失败告警发信(复用 CNB 流水线那套 QQ 邮箱授权码)

⚠️ BACKUP_PASSPHRASE 是恢复 bundle 的唯一钥匙,必须另存进密码管理器。 它不构成单点:CNB 主仓仍是明文副本,口令丢了只是少一份备份。

失败告警(scripts/backup-run.mjs)—— 这是「唯一辅仓」的必备件。 跑完备份后,退出码非 0 就通过 scripts/send_mail.js 发一封告警邮件 (主题带 ★,正文附日志尾部与常见原因清单)。成功时默认不发(避免每天一封的邮件疲劳), 加 --notify-success 才发。

为什么非做不可:「每天自动跑」的任务最典型的失败模式恰恰是静默的 —— F50 被带出门、换了网段、OpenList 重启后没起来、WebDAV 口令改过…… 没人会主动发现,直到真要用备份那天。 发信逻辑独立于备份逻辑:发信失败不改判备份的退出码,通知不该掩盖真正的故障。

定时任务:Windows 计划任务 Blog-BundleBackup,每天 03:30(本地) 执行 scripts/backup-task.cmd(默认 --verify --keep 7)。 设置:InteractiveToken + LeastPrivilege、StartWhenAvailable(错过就补跑)、 ExecutionTimeLimit=PT1H、MultipleInstances=IgnoreNew(防重入)。 日志追加到 .workbuddy-backup/logs/backup.log,超 5 MB 自动轮转。

保留 7 份 = 一周窗口(每份 605.5 MB ≈ 4.2 GB,F50 有 256 GB)。 原本是 3 份;升格为「唯一辅仓」后放宽 —— 空间不值钱,回溯窗口值钱。

★ backup-task.cmd 内容必须全 ASCII:cmd.exe 按当前代码页(zh-CN 是 GBK) 解析批处理文件,而 node 输出 UTF-8;UTF-8 中文注释会吞掉 CR/LF、 把下一行当命令执行(实测踩到:一条 rem 被当命令跑了)。 ASCII 是 UTF-8 子集,纯英文注释与 node 的中文输出混写不会乱。

恢复流程:

node scripts/backup-bundle.mjs --decrypt blog-<时间戳>.bundle.enc --out blog.bundle
git bundle verify blog.bundle      # 应报 "records a complete history"
git clone blog.bundle blog         # 或 git fetch blog.bundle 'refs/*:refs/*'

实测数据(2026-10-06):

阶段 耗时
git bundle create --all 6.8 ~ 9.9 s(605.5 MB)
AES-256-GCM 加密 1.3 ~ 2.9 s(体积不变)
WebDAV 上传 19.2 ~ 20.6 s → 29.4 ~ 31.6 MB/s
下载回读 + sha256 比对 ≈ 30 s,一致

端到端退出码 0;恢复链路已演练(解密 → git bundle verify → 1008 提交完整一致); 失败告警的邮件链路也已实测(发出一封「备份成功」验证信到 imql@qq.com)。


6. 遗留待办

# 项 说明
1 gh remote(GitHub) ✅ 已移除(2026-10-06)。GitHub 账号被标记、仓库被 AUP 清空 —— GitHub 已彻底退出本项目:远端、推送别名、发布链路 4 处硬编码、CI 定义全部清干净
2 异地备份方案 ✅ 已定案(2026-10-06):不走 git 远端,改用整仓加密 bundle → F50/OpenList(§5.6)。pushall 已收回为「只推 origin」,gitee / gitea 远端均已移除。选型依据(Gitee 两道硬门槛、Codeup 对照)保留在 §5.3 备查
3 bin/linux/hugo 出库 ✅ 不必做。那个 83.1MB 二进制只卡 Gitee 的单文件上限;既然不走 Gitee,deploy/Dockerfile 的取 hugo 方式与 .cnb.yml 的 by: 字段一行都不用改
4 gitea remote ✅ 已移除(2026-10-06)。远端仓库本身没删,需要时可 git remote add 恢复(命令见 §5.2)
5 GitHub 侧旧 workflow ✅ 已删除(2026-10-06)。整个 .github/ 目录移除(deploy.yml 1169 行 + aliyun-backup.yml + cleanup.yml),共 −1284 行 —— GitHub 已不再是任何环节的依赖。旧实现可在 git 历史中查
6 令牌 scope 缺 repo-cnb-history:r(读构建日志);补上后 agent 可自行排错
7 Gitea 主机 / 广州中转机 发布链路已不依赖;是否退役取决于其它用途
8 README.md ✅ 已更新(去 GitHub 化 + 补上备份脚本说明)
9 敏感文件仍在跟踪中 .env、GITEA_SECRETS.md、write-server/nginx/ssl/privkey.pem、content/posts/2024/.../setup-secrets.png —— 若还要推任何新平台,先 git rm --cached 并轮换凭据。⚠️ 当初「不改写历史」的唯一顾虑是备份会分叉;GitHub 那份已消失,这个顾虑没有了 → git filter-repo 现在是可行窗口(代价:全部提交 SHA 改变)。离线 bundle 已加密(§5.6),不受此影响
10 整仓离线备份 ✅ 已上线(2026-10-06),且是当前唯一的异地备份,见 §5.6。计划任务 Blog-BundleBackup 每天 03:30 跑,端到端已验证;失败会发告警邮件(已实测)。待补三件安全项:把 BACKUP_PASSPHRASE 抄进密码管理器;给 OpenList 改掉 admin 密码 + 开两步验证(现 otp: false,且旧密码已出现在对话里);确认 5244 端口未暴露到公网
11 F50 存储目录的使用约定 /本地/ 下的 刷机 / 系统 / 资料 / 软件 / 驱动 / 备份 都是用户自己在管的类别。本项目的 bundle 只写 备份/blog-bundle/ 子目录,不与用户手工备份(github-zqlit-*、local-repos-*)混放

附:相关文档

  • CNB构建落地方案.md — 迁移实施方案与实测数据
  • 代码源与构建平台选型.md — 平台对比(CNB / Gitee / GitLab / EdgeOne / 阿里云 ESA)
  • 砍COS改造步骤.md — COS 下线记录
  • EdgeOne双区域方案评估.md、Gitee方案评估.md、阿里云ESA评估.md、精简方案-只留CF和Hugo.md — 决策期评估

证据出处(现行):.cnb.yml(284 行)、deploy/Dockerfile、bin/linux/hugo、 scripts/send_mail.js、scripts/refresh_cdn.js、scripts/setup-cnb-remotes.sh、 scripts/backup-bundle.mjs、scripts/backup-run.mjs、scripts/backup-task.cmd。 原 GitHub Actions 流水线(.github/workflows/deploy.yml,1169 行)已于 2026-10-06 删除, 需要查请翻 git 历史。