chezmoi 实战:用 Git 管理多台机器的配置文件

chezmoi 是一个用 Git 管理 dotfiles 配置文件的工具,它把散落在各处的 .bashrc、.gitconfig、.vimrc、.ssh/config 等配置统一纳入版本控制,还能用模板为不同机器渲染差异化的内容,并通过加密安全保管密钥。对同时维护笔记本、台式机和云服务器的开发者来说,chezmoi 能让你一次编写、到处应用,彻底告别”换台机器就重新配一遍”的低效循环。

一、为什么需要 chezmoi

很多人的第一反应是 git init 一个裸仓库,把配置文件软链进去。这套方案在多台机器上会遇到三个绕不开的问题。

第一是差异化。公司笔记本需要配置代理和内部 CA,家里的工作站则不需要;Linux 服务器和 macOS 桌面的路径、包管理器也各不相同。裸 Git 仓库只能存一份内容,要适配多机就得堆一堆 if 判断的脚本,时间一长谁也看不懂。

第二是机密。.gitconfig 里可能藏着 GitHub token、GPG 签名身份,.ssh/config 里甚至有跳板机密码。明文提交到仓库既不安全,私有仓库也防不住误推到公开库的风险。

第三是可复现性。文件改完之后要手动 ln -s 或跑同步脚本,容易漏文件、漏步骤。GNU stow 通过软链解决了”文件放哪”的问题,却依然不解决差异化和机密管理。chezmoi 在这三者之间找到了平衡:源码(含模板)进 Git 仓库,按需渲染成目标文件,机密走加密,整个过程幂等可重复。

二、安装 chezmoi

chezmoi 是单个静态二进制,安装方式很多。macOS 用 Homebrew 最方便:

brew install chezmoi

Debian/Ubuntu 可以用官方脚本一键安装:

curl -sfL https://git.io/chezmoi | sh

装好后确认版本号,它不依赖任何运行时,所以也能直接丢进 ~/bin 自己用:

chezmoi --version

三、快速上手:把现有配置纳入管理

先用 chezmoi init 初始化本地源状态目录(默认在 ~/.local/share/chezmoi),它本质上就是一个 Git 仓库:

chezmoi init

然后把已有的配置文件”加”进去。注意 chezmoi add 是把当前真实文件复制到源状态、并建立映射,而不是直接操作你的家目录:

chezmoi add ~/.bashrc
chezmoi add ~/.gitconfig
chezmoi add ~/.vimrc

想改文件时,用 chezmoi edit 而不是 vim 直接改——它会在源状态里打开对应文件,改完你再 apply:

chezmoi edit ~/.bashrc

此时目录结构大致是:

~/.local/share/chezmoi/
├── dot_bashrc          # 对应 ~/.bashrc
├── dot_gitconfig       # 对应 ~/.gitconfig
└── dot_vimrc

文件名里的 dot_ 前缀表示目标位置的点文件;这条规则是 chezmoi 的命名约定,后面写模板时同样适用。

四、模板:让同一份配置适配多台机器

这是 chezmoi 真正的核心价值。只要把源文件命名为 .tmpl 结尾(例如 dot_gitconfig.tmpl),它就会先按 Go template 语法渲染,再写入目标位置。

变量数据源

变量有两个主要来源。其一是 .chezmoi.toml 或 .chezmoidata.toml 里自定义的键值;其二是 chezmoi 内置的机器信息,比如 .chezmoi.hostname、.chezmoi.os、.chezmoi.arch。例如一份通用的 gitconfig 模板:

# dot_gitconfig.tmpl
[user]
    name = {{ .name }}
    email = {{ .email }}
[core]
    editor = {{ if eq .chezmoi.os "darwin" }}code --wait{{ else }}vim{{ end }}

配合数据文件:

# .chezmoidata.toml
name = "yourname"
email = "you@example.com"

条件与主机名

更进一步的差异化可以用主机名判断。假设你有两台机器,一台叫 work,一台叫 home:

# dot_bashrc.tmpl
{{ if eq .chezmoi.hostname "work" }}
export HTTP_PROXY=http://proxy.corp:8080
export HTTPS_PROXY=http://proxy.corp:8080
{{ else }}
# 家用环境不设置代理
{{ end }}
alias ll='ls -alF'

这样同一份模板在 work 上会自动注入代理,在 home 上则跳过,无需维护两份文件。

五、密钥管理:用 age 安全保管敏感值

敏感值绝不能明文进 Git。chezmoi 内置了对 age 加密的支持,机密文件以 .age 加密存储,解密密钥只留在本地,不进仓库。

初始化时绑定你的 age 公钥:

chezmoi init --apply --age AGE_PUBLIC_KEY

之后把密钥写进模板,chezmoi 在 apply 时用本地私钥解密:

# dot_gitconfig.tmpl 片段
[github]
    token = {{ .age["github_token"].Plaintext }}

其中 github_token 来自加密文件 encrypted_github_token.age。只要私钥不泄露,仓库即使公开也是安全的。配合本文曾介绍的 direnv 环境变量管理,你可以把”机密值”交给 age、”环境变量”交给 direnv,职责清晰。

六、日常工作流:diff、apply 与更新

chezmoi 的工作流非常克制:先看差异,再决定是否应用。

chezmoi diff        # 预览源状态会如何改变家目录
chezmoi apply       # 真正把渲染结果写入目标文件
chezmoi verify      # 检查目标文件是否仍由 chezmoi 管理、未被手动改坏

改完源状态后推送到远端也很自然,因为它本就是 Git:

chezmoi git add -A
chezmoi git commit -m "update bashrc"
chezmoi git push

常用命令对照如下:

命令作用
chezmoi add ~/<file>把现有文件纳入管理
chezmoi edit ~/<file>编辑源状态中的对应文件
chezmoi diff预览将要发生的变更
chezmoi apply应用变更到家目录
chezmoi verify校验目标文件未被外部改动
chezmoi update拉取远端并应用(等价 git pull + apply)

七、在多台机器之间同步

chezmoi 只是 Git 之上的一层,真正的远端仓库可以是任意私有 Git 仓库。在新机器上三步到位:

brew install chezmoi
chezmoi init --apply git@github.com:yourname/dotfiles.git

--apply 会一次性完成”克隆源状态 + 渲染应用”。之后日常更新就是:

chezmoi update        # 等价于 git pull && chezmoi apply

如果你想把配置同步也接进自动化,可以在 CI(参考 GitHub Actions 实战)里对配置文件做模板语法校验,避免把渲染错误带上线。

八、chezmoi 与其他方案对比

方案差异化机密管理幂等
裸 Git 仓库需自写脚本无手动
GNU stow软链解决摆放无是
yadm直接管整个家目录支持加密是
chezmoi模板引擎age 加密是

相比 yadm,chezmoi 的模板能力更结构化,学习曲线也更平缓;相比 stow,它原生解决差异化与机密两大痛点。

九、常见坑与排障

现象原因解法
apply 后文件没变源文件漏写 .tmpl 或改了但没 edit用 chezmoi edit 改源状态再 apply
age 解密失败本地私钥丢失或不匹配用 chezmoi age 重新生成并加密
verify 报 dirty目标文件被其他程序改过chezmoi diff 比对后用 apply 覆盖或手动合并
二进制文件乱码二进制不能用模板关闭模板或直接 cp 该文件
忘记提交源状态只 apply 没 git commitchezmoi git status 检查,记得 push

十、小结

chezmoi 用”Git 存源码 + 模板渲染 + age 加密”的三段式,把多机配置这件麻烦事变得可复现、可审计。它和 direnv、git-delta、fzf、bat 这类终端工具配合,能显著提升开发环境的一致性与搭建效率。下次重装系统或拿到新机器时,一条 chezmoi init --apply 就能把熟悉的工作环境搬回来——这或许就是 dotfiles 管理最值得投入的理由。

上一篇 Kubernetes CronJob 实战:调度与失败重试
下一篇 Aider 实战:用命令行 AI 结对编程
最新评论
Docker 网络模式详解:bridge/host 生产选型 - FSData
Docker 网络模式详解:bridge/host 生产选型 - FSData
8月20日
[…] 注意最后那条:把端口绑定到 127.0.0.1,再由宿主机上的 Nginx 反代进来,比直接 -p 80:80 暴露安全得多,也方便统一做
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
8月20日
[…] Pinia 的工程化用法,可以参考我们之前的实战文章 《Vue3 组合式 API + Pinia:状态管理从入门到实战》,那里覆盖了 Sto
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
8月19日
[…] 状态,点一下就能起停容器,配合我们讲过的 Docker Compose 编排 […]
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
8月19日
[…] 缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
8月19日
[…] Docker 镜像部署。结合我们之前写的 Docker Compose 一键编排实战,可以在 CI […]