配置文件的保险箱:dotr

💡 原文中文,约11000字,阅读约需26分钟。
📝

内容提要

dotr 是一款 Rust 编写的配置备份工具,定位为“复印机”而非配置部署系统。它将指定文件复制到 Git 仓库并保存元数据,源文件保持原位。支持显式过滤、age 加密、compare-only 去噪、watch/daemon 自动备份;restore 默认仅预览,需 --apply 才写回,且 watch 永不恢复。适合希望先获得可找回副本的用户。

🔎

延伸解读

与 chezmoi 等工具的本质区别

dotr 定位为复制式备份工具,而非配置部署系统。chezmoi、yadm 等会接管源文件,通过模板、条件渲染实现跨机器部署;dotr 则保持源文件原地不动,只按清单复制到 Git 仓库。这意味着它不解决多机环境一致性,但心智负担小,适合只想为当前机器配置留一份可找回副本的用户。

restore 的保守设计意味着什么

dotr 的 restore 默认只预览,必须加 --apply 才写回;目标文件已存在且内容不同时,还需 --force 才覆盖。$HOME 之外的绝对路径更严格,要求同时提供 --apply 和 --allow-absolute。watch 模式永远不会触发 restore。这种设计把自动备份和自动恢复彻底分开,降低误覆盖风险,但恢复时需多一步确认。

加密与去噪的适用边界

age 加密需对单个路径显式开启,dotr 不会自动猜测哪些文件含秘密。若秘密已以明文进入 Git 历史,后续开启加密只能保护未来备份,历史记录仍需自行清理或轮换。normalize 用于比较时忽略易变字段,减少无意义提交,但它与 encrypt 互斥,因为加密后无法解析明文结构。两者都要求用户明确指定,而非自动推断。

使用前需留意的默认限制

dotr 默认排除 .env、私钥、缓存、日志、数据库等,二进制文件默认跳过,文件大小上限 20MiB。symlink 默认跟随并复制目标内容,如需保留链接本身需设 follow_symlink = false。工具尚年轻,接口和默认策略可能变化,建议先用隔离仓库试跑,再指向真实配置。

❓

Q&A

dotr 和 chezmoi 这类 dotfiles 工具的核心区别是什么?

dotr 定位是复制式备份工具,不是配置部署系统。chezmoi 等工具会把 home 目录变成可部署的配置系统,涉及模板、条件渲染、跨机器 bootstrap 和 secret manager;而 dotr 只把你指定的文件复制到 Git 仓库并保存元数据,源文件仍在原地,不接管你的 home 目录。

dotr 的 restore 默认行为是什么?为什么这样设计?

dotr restore 默认是 dry-run,只预览不写回,必须加 --apply 才会真正恢复。如果目标文件已存在且内容不同,默认拒绝覆盖,除非再加 --force。$HOME 之外的绝对路径更严,必须同时给 --apply 和 --allow-absolute。这样设计是因为作者认为 backup 可以勤快,restore 应该慢一点,避免一次错误覆盖导致环境难以排查。

dotr 如何避免把缓存、日志、token 等噪音文件备份进仓库?

dotr 默认会跳过缓存、日志、本地数据库、session、build output、临时文件、.env、私钥等,二进制默认也不进仓库。配置主要围绕 [[path]] 和 [[path_set]],推荐显式写 include 而不是整个目录打包。如果确实要备份被默认排除的文件,可以用 --force 或路径级 force = true,但需要自己清楚风险。

dotr 的 age 加密怎么用?有什么注意事项?

对单个 path 显式开启 age 加密:先 dotr keygen 生成密钥,再 dotr add --encrypt ~/.npmrc。recipients 是公钥可以进仓库,~/.config/dotr/identity 是私钥必须像密码一样保存,不能提交。加密后的文件带 .age 后缀,index.json 仍记录明文路径但明文内容不会进仓库。dotr 不会自动猜哪些文件该加密,需要你明确指定。另外,如果 secret 已经以明文进过 Git 历史,后来开启加密只能保护未来的备份,历史记录不会自动消失。

dotr 的 normalize 是做什么的?为什么不能和 encrypt 一起用?

normalize 用于对匹配到的文件做只用于比较的字段删除,比如时间戳、计数器等每次都会变但无备份价值的字段。它不改源文件,也不改仓库备份,只是在算 hash 比较时先 drop 掉指定字段,避免这些噪音导致 Git 历史频繁变动。它不能和 encrypt = true 一起用,因为加密备份比较的是密文,比较阶段不该去解析明文。

dotr 的 watch 和 daemon 模式是如何工作的?

dotr watch 会监听配置里的 source path,做 debounce,再按 backup_interval_secs 控制频率。dotr daemon start 会在后台启动 watch,注册监听后先跑一次完整 backup 以补上停机期间的改动,之后只备份变化过的路径。日志默认在 ~/.local/state/dotr/dotr-watch.log。关键一点:dotr watch 永远不会 restore,自动备份可以,自动把文件盖回去不行。

dotr 的 [[custom_backup]] 是解决什么问题的?

有些东西不是磁盘上现成的文件,比如 Homebrew 包列表、VS Code 扩展列表,需要跑一条导出命令才会生成文件。[[custom_backup]] 用来描述这种关系:backup 前先跑 backup 命令生成文件再扫描,restore 时文件恢复后再跑 restore 命令。dry-run 只打印命令不执行。这样就不用再维护外面的 bootstrap 脚本,备份关系直接写在 dotr.toml 里。

dotr 备份仓库的目录结构是怎样的?路径映射规则是什么?

仓库根下有 dotr.toml、files/、metadata/。files/home 对应 $HOME 下的文件,files/root 对应 home 之外的绝对路径,files/root 是懒创建的。metadata/index.json 记录权限、是否加密、对应源路径等信息。路径映射直接且可逆,比如 ~/.zshrc 映射到 files/home/.zshrc。

使用 dotr 时有哪些实际注意事项?

第一,仓库可以是私有的,但私有不等于可以塞明文私钥,~/.ssh/id_rsa、GnuPG 私钥这类没有单独恢复和轮换方案就不要备份,token 类小文件用 --encrypt。第二,默认排除名单很长,真要备份其中某个文件用 --force 并心里有数。第三,二进制默认跳过,文件大小默认上限 20MiB。第四,symlink 默认 follow,复制的是目标内容,要保存软链事实需设 follow_symlink = false。第五,dotr check 值得在 CI 或定期跑。第六,这是个人向小工具,接口和默认策略还可能变,先用隔离仓库试。

🏷️

标签

➡️

继续阅读