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




