备份策略 — 操作日志
记录恢复演练记录、手动操作备忘。
格式
## YYYY-MM-DD: 操作简述
- **类型:** 恢复演练 / 手动操作 / 配置变更
- **触发原因:** 常规演练 / 故障恢复 / 配置变更
- **操作内容:**
- **耗时:**
- **结果:** 成功 / 部分成功 / 失败
- **备注:**
2026-05-30: 备份方案阶段复盘(定稿)
- 类型: 阶段性反思
- 审阅人: 用户 + 大锤(Hermes Agent)
- 操作内容: 详见下方——汇总决策、弯路、经验
- 结果: 完成 ✅
决策记录
| 决策 | 选择 | 理由 |
|---|---|---|
| 备份工具 | restic + resticprofile | 去重+加密成熟稳定,resticprofile 统一管理多 profile 和调度 |
| 密码存储 | macOS Keychain | FileVault 未开,Keychain 系统级加密比明文文件更安全 |
| 密码策略 | 本地盘 + NAS 共用同一 restic 密码 | 简化管理(ADR Phase 4.1.1) |
| profile 分层 | P0-P3 四级 | 按敏感度 + 变动频率分级,高频小数据(P0)与低频大数据(P2)分开 |
| P0 调度方式 | 无独立 schedule,通过 daily group 触发 | 配置不常变,无需单独定时启动 |
| 调度格式 | resticprofile 日程表达式 → launchd plist | resticprofile schedule 将日程转为 macOS launchd 服务 |
| 配置结构 | resticprofile 0.33 标准格式(version: "1" + profile 级 key) | 0.32 的 flat 旧格式已废弃,新版用标准 YAML |
| 旧方案处理 | 保留 backup.sh(tar+gz)但未标注废弃 | 需补充 # DEPRECATED 避免混淆 |
| 外置盘未挂载 | backup-run.sh 失败不阻塞 | 失败日志可读,但无缓重或告警机制 |
| 云存储 | 暂缓 | 成本 + 外置盘未到位,先做本地部分 |
弯路记录
- resticprofile 配置格式 ~8 轮修复 — 0.33 与早期版本的 YAML 结构差异大。应先用
resticprofile dump验证解析结果,不要盲信文档图示。 - Keychain ACL 理解不足 —
set-key-partition-list只适用于证书/key 条目,通用密码用add-generic-password -A即可,不需要 ACL 额外授权。 set -e习惯性加但不严谨 —grep无匹配导致脚本提前退出,基本功问题。- p0 无独立 schedule 导致多轮调整 — 首次
resticprofile schedule --all只生成 p1/p2/p3 的 plist,后发现 schedule 只对有backup.schedule字段的 profile 生效。p0 通过 group 触发是设计选择,不是疏忽。 - 旧 backup.sh 未清理 — tar+gz 旧脚本仍留在
DEV/scripts/,新用户可能被误导。 - launchd plist 未做外置盘依赖检查 — 3 个 plist 按时间触发,但外置盘可能未挂载,restic 报错后 launchd 记失败。无缓重机制,外置盘首次接入前定时任务会持续失败。
经验归档
- 先 dump 再信文档 — 新版本工具先用
resticprofile dump验证配置解析,不要盲信文档图示。 - Keychain ACL 场景区分 — 通用密码用
add-generic-password -A允许所有应用访问即可;set-key-partition-list只适用于钥匙串中的 key/证书条目,不是通用密码的替代方案。 - group 调度规则 —
schedule只对有backup.schedule字段的 profile 生成 plist。无独立 schedule 的 profile(如 p0)通过 group 触发。 - 分层备份的核心价值在恢复 — 备份速度差不多,但恢复时的选择性天差地别。P0 逐级恢复最大程度缩短关键数据 RTO。
- 外置盘依赖的定时任务 — launchd + 可移动介质需考虑 graceful failure:失败日志可读、不影响启动、恢复后自动重试。
- 新旧方案及时清理 — 旧脚本标注
# DEPRECATED或移出 PATH,避免混淆。 - 纯本地只能做到 2-1 — 3-2-1 策略的”异地”副本必须依赖云或 NAS。
外置盘容量提示
P1 ~67GB(DEV + Documents + Pictures)+ P2 ~12GB(Downloads + Movies/Music)+ restic 元数据 + 多版本快照。建议外置盘 ≥ 256GB,首次全量前确认可用空间足够。backup-init.sh 已有 df 检查作为防线。
2026-05-30: launchd 定时任务 + 初始化脚本
- 类型: 配置变更
- 操作内容:
- profiles.yaml 中所有 profile 增加 schedule(systemd 日历格式)
resticprofile schedule --all生成 3 个 launchd plist- 写
backup-init.sh— 外置盘接入后一键初始化 repo + 首次备份 - 写
backup-run.sh— 后续手动运行备份(支持 p0/p1/p2/p3/daily/full)
- 结果: 成功 ✅
- 备注: p0 无独立 schedule(配置不常变),通过
dailygroup 或backup-run.sh full触发
2026-05-30: Keychain ACL 修正
- 类型: 配置变更
- 操作内容:
set-key-partition-list不支持通用密码条目,改用-A标志重建 Keychain 条目,launchd 进程可直接读取 - 结果: 成功 ✅
2026-05-30: resticprofile 配置 + 关键词扫描脚本
- 类型: 配置变更
- 触发原因: Phase 4/6 实施
- 操作内容:
- 生成 restic repo 密码(32 字节随机),存入 macOS Keychain(服务名
restic-password) - 写
~/.config/resticprofile/profiles.yaml:p0(密钥配置)/p1(代码文档)/p2(媒体)/p3(系统配置)四个 profile - 写
~/DEV/scripts/backup-keyword-scan.py+~/.config/backup-keyword-scan.yaml默认配置 - 扫描备份策略文档验证:检出 6 处命中(ADR 合规讨论区的”机密”和”客户信息”——误报,扫描机制正常)
- 生成 restic repo 密码(32 字节随机),存入 macOS Keychain(服务名
- 结果: 成功
- ✅ resticprofile 4 个 profile 全部正确解析
- ✅ 关键词扫描脚本可运行,首次自动生成默认配置
- ⏳ ACL 配置待执行(需登录密码)
- ⏳ repo 初始化待执行(需外置盘)
- 备注: 关键词扫描脚本集成到云出境步骤(非本地备份),待 Phase 5 实施时挂载
2026-05-30: SOPS + age 原型验证
- 类型: 手动操作
- 触发原因: 常规验证
- 操作内容: 验证 SOPS + age 加密→git→解密恢复全链路。加密对象为 GenericAgent/mykey.py(真实密钥模板文件,43727 字符)
- 结果: 成功
- ✅ age 密钥对生成正常
- ✅ SOPS + age 加密成功,输出为 JSON 格式(AES256_GCM + age 封装)
- ✅ 解密后与原文件完全一致(diff 确认)
- ✅ 密钥导出格式正确,可存入密码管理器
- 安装方式:
brew install age sops,安装到/opt/homebrew/Cellar/ - 备注: 原型通过,SOPS + age 工作流可实施