来源:notes/topics/environment_backup_restore/README.md

工作站环境:云端备份与一键恢复

目标:把整台工作机的环境变成”云上可复原的产物”。任意一台新机器, 装完系统后跑一条命令,就能在 30 分钟内回到当前工作状态。

硬约束:云是唯一中转。禁止机器之间 scp/rsync/直连同步。 即便原有两台机器全部损坏,只要能上网,就能重建。

调研明细见 cloud-options-research.md(含一手来源引用)。 备份机的不可变系统机制与重启连通性实测见 deepin-immutable-and-reboot-verification.md


实现状态

组件 状态
scripts/collect-manifest.sh ✅ 已实现,可运行
inventory/ ✅ 已生成(本机实测清单)
cloud-options-research.md ✅ 已完成
nas-vm-sync.md / backup-machine-setup.md ✅ 已完成
deepin-immutable-and-reboot-verification.md ✅ 已完成(含真实重启验证)
bootstrap.sh ⬜ 未实现(设计中的新机引导脚本)
restore.sh ⬜ 未实现(Layer 4 运行时重建)
backup.sh / verify.sh ⬜ 未实现(定时备份与自检)
inventory/manifest.json ⬜ 未实现(云上对象校验和清单)

下面章节里提到的 bootstrap.shrestore.shbackup.shverify.sh 均为设计目标,尚未落地,不要去找这些文件。

1. 盘点结论:真正”不可重建”的只有 ~3 GB

本机 /home 占 33 GB,但其中绝大部分是可重建的运行时,不该上传。

类别 体积 处置
nvm / node 587 MB 重建
Go 工具链 + ~/go 1.7 GB 重建
~/src(ruby 源码) 606 MB 重建
node_modules 383 MB 重建
.venv(绝对路径写死) ~1.1 GB 重建
.git 对象库 ~600 MB 重新 clone
不可重建数据 ~2.97 GB 上云

不可重建数据的构成(实测):

项目 体积 备注
bilibili_transcripts/BV1uu5WzvEnn 1848 MB 其中 horizon-2025.wav 1.6 GB;文本转写仅 ~600 KB
codex_personal_assistant/{notes,migration-artifacts,data} 252 MB  
~/.codex/{sessions,skills} 447 MB  
~/stock_monitor 178 MB  
ashare_monitor/{logs,reports,company_analyze} 208 MB  
~/.cc-connect-qqbot/codex 89 MB  
~/.dsh 28 MB 含凭据
密钥 / 配置 / units / crontab < 20 MB 见 Layer 1/2

结论:免费额度就能装下。 Cloudflare R2 送 10 GB、Backblaze B2 送 10 GB、 腾讯 COS 送 50 GB×6 个月 —— 全部覆盖 3 GB。


2. 分层模型

每一层用不同的机制,混用会互相打架。

Layer 0 — OS 基线(不备份,只记录版本)

  • Deepin 25 官方 ISO(安装介质本身就是”备份”)
  • apt-mark showmanual / dpkg --get-selections(本机 2351 个包)
  • ll-cli list(linglong 应用:deepin-browser / deepin-mail / dde-calendar)
  • 第三方 apt 源:/etc/apt/sources.list.d/{appstore,driver,zerotier}.list

Layer 1 — 声明式配置(小,进私有 Git 仓库)

  • dotfiles:.bashrc .profile .gitconfig .imwheelrc
  • ~/.config/systemd/user/*.{service,timer} + default.target.wants
  • crontab -l(含 ashare_monitor 的 6 条 sync + 2 条行情同步)
  • ~/.config/{ashare_monitor,astro,go,nvm} 的非机密部分
  • 本项目里的 bootstrap.sh / restore.sh

Layer 2 — 密钥凭据(小,必须加密,绝不能明文进 Git)

  • ~/.ssh/id_ed25519~/.gnupg/
  • ~/.cc-connect*/config.toml(含 app_secretapi_key)
  • ~/.dsh/.credentials.yaml~/.codex/auth.json
  • ~/.lark-cli/~/.Monocloud.json
  • ~/.config/ashare_monitor/cycle_web.env
  • ~/.git-credentials(如存在)

处置:打包成 secrets.tarage 加密 → 提交进私有仓库。 解密的私钥是唯一需要人为保管、不能上云的东西(密码管理器 + 纸质各存一份)。

Layer 3 — 不可重建数据(~3 GB,进 restic → 对象存储)

restic 提供客户端加密、去重、增量、单文件恢复。仓库密码同样属于”不能上云”的范畴。

Layer 4 — 可重建运行时(不备份)

nvm/node、Go、ruby、.venvnode_modules~/go/pkg.cache。 全部由 restore.sh 重建。.venv 里写死了 /home/admin/... 绝对路径, 复制过去反而会坏,必须重建。


3. 传输通道选型(本机实测,2026-09-18)

10.71.48.85 上的实测:

目标 冷启动 稳定吞吐 结论
GitHub HTTPS 33 KB/s,建连 5s 3.5–4.7 MB/s 冷启动慢、方差大
GitHub git clone 大仓库 linux 浅克隆 90s 后断流 不可靠 不适合大对象
Gitee HTTPS 1.4–2.7 MB/s 稳定,国内首选
npm registry 0.7–2.0 MB/s 可用
OneDrive 不可达 排除
HuggingFace 不可达 排除

推荐组合:

  • Layer 1 + Layer 2 → Gitee 私有仓库为主,GitHub 作镜像(已用 andywu1998/cc-connect 等)
  • Layer 3 → 国内对象存储(阿里 OSS ¥0.12/GB·月 / 腾讯 COS 送 50GB×6月 / 七牛)
    • 想先用免费额度:R2 或 B2,但必须先实测本机到该端点的速度再定
  • 不要用 GitHub 存大文件:单文件硬上限 100 MiB,仓库建议 <1 GB,免费 LFS 仅 10 GiB
  • 不要依赖 Syncthing/Tailscale/ZeroTier 做传输:默认走 P2P,违反硬约束
  • 不要用阿里云盘/百度网盘/夸克的第三方桥:rclone 无官方后端,封号风险未量化

4. 新机器恢复流程(目标 <30 分钟)

装 Deepin 25 ISO
   └─> curl -fsSL <bootstrap-url> | bash
          ├─ 安装 git/curl/age/rclone/restic
          ├─ clone 私有配置仓库(Gitee)
          ├─ 用 age 私钥解开 secrets.tar → 还原 SSH/GPG/凭据
          ├─ 安装并加入 ZeroTier
          ├─ 恢复 apt 清单 + linglong 应用
          ├─ 安装 nvm/node@v22.23.2、Go 工具链
          ├─ clone 各业务仓库(cc-connect / ashare_monitor / blog / ...)
          ├─ 重建 .venv 与 node_modules
          ├─ 恢复 systemd --user units + crontab + enable timers
          ├─ 拉起 cc-connect(见第 5 节)
          └─ restic restore(从对象存储拉 Layer 3)
   └─> 通过 QQ bot 确认就位 → SSH over ZeroTier 接管

5. QQ 机器人 = 新机器的引导通道

要解决的问题: 全新机器装好后没有任何入口 —— 不在身边、没有公网 IP、 SSH 未配置、ZeroTier 未授权。这时你无法登录进去完成剩下的恢复。

解法: QQ bot 走 WebSocket 长连接外呼,不需要任何入站端口, 在 NAT 后面也能连出来。因此:

  1. 为每台机器配一个独立 QQ bot(或同一 bot 下不同 [[projects]]), 凭据放在加密的 secrets 包里 —— 这里就是”另外一个 QQ 机器人”的用处。
  2. bootstrap 的最后一步自动启动 cc-connect,work_dir 指向工作区。
  3. bot 一上线就主动推一条消息(“<hostname> 已就位,当前恢复进度 X/Y”)。
  4. 你从 QQ 发指令,让新机器上的 agent 自己跑完剩余恢复步骤。
  5. 恢复完成后,再用 ZeroTier 内网 IP 走 SSH 常规操作。

这条通道是唯一不依赖入站网络的引导路径,必须做成幂等、可重入。


6. 一致性保障

  • 单向主从:本机(主)→ 云 → 新机(从)。永远不做双向同步,避免互相污染。
  • 每日自动备份:systemd timer 跑 backup.sh,失败通过 QQ bot 告警。
  • 每周自检:verify.sh 在临时目录做一次 dry-run 恢复,校验清单。
  • 清单化:inventory/manifest.json 记录”云上必须存在哪些对象 + 校验和”, 任何一项缺失即告警。这是防止”以为备份了其实没有”的关键。
  • 备份仓库不能放进被备份的目录(循环引用)。

7. 已知风险 / 待验证

风险 说明
Deepin 25 /usr 只读(“Solid” 不可变) apt 批量恢复可能受限,需在目标机实测;可能只能恢复用户层
.venv 绝对路径 必须重建,不能复制
备份密码单点 restic 密码 + age 私钥必须离线保管,丢了就全丢
Gitee 仓库配额 官方帮助页未能抓取,待登录后确认仓库/单文件上限
腾讯 COS 国内单价 文档 JS 渲染未能提取,待控制台确认
本机到 R2/B2 的实测速度 需在选定后实测

8. 待决事项

  1. 对象存储选哪家?(阿里 OSS / 腾讯 COS / 七牛 / 先白嫖 R2·B2)
  2. 那个新 QQ bot 是给新机器做引导通道,还是替换现在这个?
  3. 1.6 GB 的 horizon-2025.wav 要不要备份?(丢源视频就找不回了,但占一半体积)
  4. 是否接受把密钥加密后上传云?(否则新机器无法全自动恢复)