chezmoi: 跨机器 Dotfiles 管理¶
为什么要学 chezmoi¶
每个开发者都有一堆配置文件(dotfiles):.bashrc、.gitconfig、.vimrc、.config/ 下的各种配置……当你换了一台新电脑,或者需要在多台机器上保持一致的开发环境时,管理这些配置就变成了痛苦。
传统方案(如 GNU Stow、裸 Git 仓库)虽然能用,但在以下场景中力不从心:
| 痛点 | 传统方案 | chezmoi |
|---|---|---|
| 不同机器需要不同配置 | 手动维护分支 | 模板引擎 + 条件判断 |
| 配置中包含密钥/Token | 不安全或需要额外加密 | 集成 1Password/Bitwarden/age |
| 安装到新机器 | 需要多步手动操作 | chezmoi init --apply 一行完成 |
| 查看变更差异 | git diff (可能遗漏) | chezmoi diff 精确显示 |
| 批量更新 | 手动同步 | chezmoi update |
chezmoi(发音 /ʃeɪ mwa/,法语"我家"的意思)用 Go 编写,是目前最成熟的 dotfiles 管理工具。
核心概念¶
白话解释¶
chezmoi 的工作方式分两层:
- 源状态(Source State):存储在
~/.local/share/chezmoi/中的 Git 仓库,是你配置文件的"真相来源" - 目标状态(Target State):你家目录中的实际配置文件
chezmoi 负责把源状态同步到目标状态。中间可以经过模板渲染、密钥解密等处理。
源仓库 (~/.local/share/chezmoi/) 目标 (~/)
├── dot_bashrc → .bashrc
├── dot_gitconfig.tmpl → .gitconfig (模板渲染后)
├── dot_config/ → .config/
│ └── fish/config.fish → .config/fish/config.fish
└── private_dot_ssh/ → .ssh/ (权限 0700)
└── private_config → .ssh/config (权限 0600)
核心概念表¶
| 概念 | 说明 |
|---|---|
| Source Directory | 源仓库目录 (~/.local/share/chezmoi/) |
| Target Directory | 目标目录(通常是 ~/) |
| 文件名前缀 | 控制文件属性的命名约定 |
.tmpl 后缀 | 标记文件为 Go 模板 |
.chezmoi.toml | chezmoi 配置文件(在 ~/.config/chezmoi/) |
chezmoiignore | 忽略规则文件 |
| External | 从外部 URL 下载的资源 |
文件名前缀约定¶
| 前缀 | 效果 | 示例 |
|---|---|---|
dot_ | 目标文件名以 . 开头 | dot_bashrc → .bashrc |
private_ | 文件权限设为 0600 | private_dot_ssh/private_config |
readonly_ | 只读权限 | readonly_config |
exact_ | 目标目录精确匹配(删除多余文件) | exact_dot_config/ |
executable_ | 可执行权限 | executable_script.sh |
encrypted_ | 加密文件 | encrypted_private_key |
modify_ | 修改脚本而非覆盖 | modify_dot_bashrc |
run_ | 运行脚本 | run_once_install.sh |
run_once_ | 只运行一次的脚本 | run_once_setup.sh |
run_onchange_ | 内容变化时运行 | run_onchange_reload.sh |
安装配置¶
安装方式¶
macOS
Linux
# 通用安装脚本
sh -c "$(curl -fsLS get.chezmoi.io)"
# Arch Linux
pacman -S chezmoi
# Ubuntu/Debian
sudo snap install chezmoi --classic
Windows
初始化¶
# 全新初始化
chezmoi init
# 从已有的 GitHub 仓库初始化
chezmoi init https://github.com/your-username/dotfiles.git
# 初始化并立即应用
chezmoi init --apply https://github.com/your-username/dotfiles.git
配置 chezmoi¶
# ~/.config/chezmoi/chezmoi.toml
[data]
name = "你的名字"
email = "you@example.com"
work = false
[git]
autoCommit = true
autoPush = false
[edit]
command = "code"
args = ["--wait"]
[merge]
command = "code"
args = ["--wait", "--merge"]
快速上手¶
添加第一个配置文件¶
# 添加现有的配置文件到 chezmoi
chezmoi add ~/.bashrc
chezmoi add ~/.gitconfig
chezmoi add ~/.config/fish/config.fish
chezmoi add ~/.ssh/config
# 添加整个目录
chezmoi add ~/.config/helix
# 查看 chezmoi 管理的文件列表
chezmoi managed
编辑配置¶
# 编辑 chezmoi 管理的文件(在源仓库中编辑)
chezmoi edit ~/.bashrc
# 编辑后查看差异
chezmoi diff
# 应用变更
chezmoi apply
# 编辑后直接应用
chezmoi edit --apply ~/.bashrc
查看和同步¶
# 查看源状态和目标状态的差异
chezmoi diff
# 应用所有变更
chezmoi apply
# 应用前预览(dry-run)
chezmoi apply --dry-run --verbose
# 进入源仓库目录
chezmoi cd
# 在这里可以 git add, commit, push 等
用 Git 管理¶
# 进入源仓库
chezmoi cd
# Git 操作
git add .
git commit -m "Add initial dotfiles"
git remote add origin https://github.com/you/dotfiles.git
git push -u origin main
# 退出源仓库
exit
# 或者使用 chezmoi git 子命令
chezmoi git add .
chezmoi git commit -- -m "Update configs"
chezmoi git push
在新机器上恢复¶
# 一行命令搞定
chezmoi init --apply https://github.com/you/dotfiles.git
# 等价于
# chezmoi init https://github.com/you/dotfiles.git
# chezmoi apply
进阶用法¶
模板系统¶
chezmoi 使用 Go 的 text/template 模板语言,可以根据机器差异生成不同配置:
# dot_gitconfig.tmpl
[user]
name = {{ .name }}
email = {{ .email }}
{{ if .work -}}
[url "git@github.com:company/"]
insteadOf = https://github.com/company/
{{ end -}}
[core]
{{ if eq .chezmoi.os "darwin" -}}
editor = code --wait
{{ else -}}
editor = vim
{{ end -}}
模板中可用的变量:
| 变量 | 说明 |
|---|---|
.chezmoi.os | 操作系统 (darwin/linux/windows) |
.chezmoi.arch | CPU 架构 (amd64/arm64) |
.chezmoi.hostname | 主机名 |
.chezmoi.username | 用户名 |
.chezmoi.homeDir | 家目录路径 |
.name, .email 等 | chezmoi.toml 中 [data] 定义的自定义数据 |
条件化包含文件¶
# .chezmoiignore
# 根据操作系统忽略不需要的文件
{{ if ne .chezmoi.os "darwin" }}
dot_config/karabiner/ # macOS 专用
Library/ # macOS 专用
{{ end }}
{{ if ne .chezmoi.os "linux" }}
dot_config/i3/ # Linux 专用
dot_xinitrc # Linux 专用
{{ end }}
密钥管理¶
使用 age 加密
# 生成 age 密钥
age-keygen -o ~/.config/chezmoi/key.txt
# 配置 chezmoi 使用 age
# ~/.config/chezmoi/chezmoi.toml
[age]
identity = "~/.config/chezmoi/key.txt"
recipient = "age1..."
# 添加加密文件
chezmoi add --encrypt ~/.ssh/id_ed25519
chezmoi add --encrypt ~/.config/gh/hosts.yml
# 文件在源仓库中是加密的
cat $(chezmoi source-path ~/.ssh/id_ed25519)
# → 加密内容,无法直接读取
使用 1Password
# dot_gitconfig.tmpl
[user]
name = {{ .name }}
email = {{ .email }}
signingkey = {{ onepasswordRead "op://Personal/GPG Key/public key" }}
使用 Bitwarden
运行脚本¶
# run_once_install-packages.sh.tmpl
#!/bin/bash
{{ if eq .chezmoi.os "darwin" -}}
brew install fish helix ripgrep fd bat
{{ else if eq .chezmoi.os "linux" -}}
sudo apt install -y fish ripgrep fd-find bat
{{ end -}}
# run_onchange_fish-plugins.sh.tmpl
#!/bin/bash
# 当这个文件内容变化时重新运行
# 下面的 hash 注释确保内容变化时触发
# hash: {{ include "dot_config/fish/fish_plugins" | sha256sum }}
fisher update
External 下载¶
从外部 URL 自动下载资源:
# ~/.local/share/chezmoi/.chezmoiexternal.toml
# 下载 Oh My Zsh
[".oh-my-zsh"]
type = "archive"
url = "https://github.com/ohmyzsh/ohmyzsh/archive/master.tar.gz"
exact = true
stripComponents = 1
refreshPeriod = "168h" # 每周刷新
# 下载单个文件
[".local/bin/delta"]
type = "file"
url = "https://github.com/dandavison/delta/releases/latest/download/delta-x86_64-unknown-linux-gnu.tar.gz"
executable = true
# 下载 Git 仓库
[".tmux/plugins/tpm"]
type = "git-repo"
url = "https://github.com/tmux-plugins/tpm.git"
refreshPeriod = "168h"
交互式配置(首次安装提示)¶
# .chezmoi.toml.tmpl(注意是模板文件)
[data]
name = {{ promptString "Your full name" | quote }}
email = {{ promptString "Your email" | quote }}
work = {{ promptBool "Is this a work machine" }}
{{ if .work -}}
company = {{ promptString "Company name" | quote }}
{{ end -}}
首次 chezmoi init 时,会交互式询问这些值。
常见问题¶
Q1: chezmoi 和 GNU Stow 比有什么优势?¶
| 功能 | GNU Stow | chezmoi |
|---|---|---|
| 模板 | 无 | Go 模板 |
| 密钥管理 | 无 | age/1Password/Bitwarden |
| 跨平台差异 | 手动管理分支 | 模板条件判断 |
| 安装脚本 | 手动 | run_once_ 脚本 |
| diff 预览 | 需要手动比较 | chezmoi diff |
Q2: 可以管理 root 用户的配置吗?¶
chezmoi 默认管理当前用户的家目录。root 配置需要单独的 chezmoi 实例,或使用 run_ 脚本复制文件。
Q3: 怎么处理已经存在的配置文件?¶
# chezmoi add 会将现有文件复制到源仓库
chezmoi add ~/.bashrc
# 如果源和目标有冲突
chezmoi merge ~/.bashrc
# 使用配置的 merge 工具解决冲突
Q4: 如何排除某些文件不被管理?¶
Q5: 自动提交和推送怎么设置?¶
# chezmoi.toml
[git]
autoCommit = true # 每次 chezmoi add/edit 后自动 commit
autoPush = true # 自动 push(谨慎使用)
Q6: chezmoi 的学习曲线如何?¶
基础用法(add/edit/apply/diff)5 分钟可以学会。模板和密钥管理需要额外学习,但可以渐进式采用——先简单管理文件,需要时再加模板。
参考资源¶
| 资源 | 链接 |
|---|---|
| 官方网站 | https://www.chezmoi.io |
| GitHub 仓库 | https://github.com/twpayne/chezmoi |
| 快速入门 | https://www.chezmoi.io/quick-start/ |
| 用户指南 | https://www.chezmoi.io/user-guide/command-overview/ |
| 模板参考 | https://www.chezmoi.io/user-guide/templating/ |
| 常见 dotfiles 示例 | https://www.chezmoi.io/links/dotfile-repos/ |
总结:chezmoi 是 dotfiles 管理的"终极方案"。简单场景下它和 Stow/裸 Git 一样简单,但在多机器差异化配置、密钥安全管理、自动化安装这些进阶场景下,它的模板系统和密钥集成是其他方案无法匹敌的。如果你有两台以上的机器需要保持配置同步,chezmoi 值得投入学习时间。