.zshrc.gitconfig、Neovim 配置、终端主题——这些散落在 ~ 目录的文件不是零散偏好,而是个人工程环境的源代码。它们决定你的命令行行为、编辑器感觉、Git 身份和开发工具链接方式。不管理它们意味着:换机器就重装一遍、多台机器配置各自漂移、某次误操作删了文件找不回来。

1. 为什么需要管理

四个现实问题:

  • 换电脑:几十个配置文件分散在 ~/~/.config/~/.local/ 各处,手动复制容易遗漏,也不知道遗漏了什么
  • 多机同步:家里台式机、公司笔记本、云服务器——改了这边,那边不知道
  • 机器差异:macOS 和 Linux 路径不同,工作电脑需要加载公司内网代理,个人电脑不需要
  • 敏感信息:API key、数据库密码、GitHub token 不能直接提交到公开 Git 仓库

管理方式从简到繁,按实际需求选:配置少、机器同类用 Git + 符号链接;配置量增长、出现多机差异或敏感信息时,chezmoi 接手。

2. 最简方式:Git + 符号链接

把配置文件移进一个 Git 仓库,再用符号链接把它们部署回原位。这是最直接的方案,没有任何工具依赖。

# 建仓库
mkdir -p ~/dotfiles && cd ~/dotfiles && git init
 
# 把配置移进来
mv ~/.zshrc ~/dotfiles/zshrc
mv ~/.gitconfig ~/dotfiles/gitconfig
 
# 用符号链接部署回去
ln -s ~/dotfiles/zshrc ~/.zshrc
ln -s ~/dotfiles/gitconfig ~/.gitconfig
 
# 提交
git add . && git commit -m "feat: initial dotfiles"

换新机器时:

git clone <你的仓> ~/dotfiles
ln -s ~/dotfiles/zshrc ~/.zshrc
ln -s ~/dotfiles/gitconfig ~/.gitconfig
# ... 每个文件重复一遍,或者写个脚本

适合的情况:配置文件少于 10 个、只在同类机器(全是 macOS 或全是 Linux)上使用、没有需要按机器区分的配置、没有敏感信息要保护。

局限:手动维护符号链接脚本会随配置增长变繁琐;无法优雅处理”工作机器加载这段,个人机器不加载”这类需求;敏感信息只能排除在仓库外,没有统一管理方案。

3. 升一级:chezmoi

chezmoi 解决了 Git + 符号链接处理不了的问题:模板化差异、敏感信息分级、apply 前预览变更、新机器一条命令恢复。

核心设计

chezmoi 的核心是双层模型:source 目录(你管理的”源码”)和 target 目录(实际生效位置)分离。

source(~/.local/share/chezmoi/)     →     target(~/)
  dot_gitconfig.tmpl                 →     .gitconfig
  dot_zshrc                          →     .zshrc
  dot_config/nvim/init.lua           →     .config/nvim/init.lua

Source 目录是一个普通 Git 仓库,可以推到 GitHub。chezmoi 把 source 里的文件渲染后部署到家目录对应位置。多次 apply 效果相同(幂等),可安全用于自动化脚本。

基础操作

# 初始化
chezmoi init && cd $(chezmoi source-path)
git remote add origin <仓库地>
 
# 纳入管理(文件被复制到 source,自动加 dot_ 前缀)
chezmoi add ~/.zshrc
chezmoi add ~/.gitconfig
chezmoi add ~/.config/nvim/  # 整个目录也可以
 
# 编辑配置
chezmoi edit ~/.zshrc          # 在 source 目录里编辑
chezmoi apply                  # 部署到 target
 
# 查看差异(apply 前先看)
chezmoi diff
chezmoi status
 
# 推送到远端
cd $(chezmoi source-path) && git add . && git commit -m "..." && git push

重要习惯:永远通过 chezmoi edit 修改配置,不要直接改 target 文件——下次 apply 会被覆盖。apply 前先运行 chezmoi diff,看清楚准备改什么。

新机器一键恢复

chezmoi init --apply https://github.com/你/dotfiles

这条命令会克隆仓库、初始化 chezmoi、运行模板渲染、部署到家目录。真正重要的不是命令短,而是这条路径可重复、可审计、可写进新机器初始化流程或 Ansible 脚本。

4. 模板化处理机器差异

不同机器需要不同配置,模板是 chezmoi 区别于简单 Git 方案的核心能力。

文件名加 .tmpl 后缀即被 chezmoi 当作 Go 模板处理:

dot_gitconfig.tmpl  →  渲染后部署为  .gitconfig
dot_zshrc.tmpl      →  渲染后部署为  .zshrc

内置模板变量

{{ .chezmoi.os }}        # 操作系统:darwin / linux / windows
{{ .chezmoi.hostname }}  # 主机名
{{ .chezmoi.username }}  # 用户名

chezmoi data 打印所有可用变量。

按操作系统区分路径

# dot_zshrc.tmpl
{{- if eq .chezmoi.os "darwin" }}
export PATH="/opt/homebrew/bin:$PATH"
{{- else }}
export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
{{- end }}

按主机名区分工作和个人配置

# dot_zshrc.tmpl
{{- if eq .chezmoi.hostname "work-macbook" }}
export WORK_PROXY="http://proxy.company.com:8080"
{{- else }}
# 个人机器不需要代理
{{- end }}

gitconfig 凭据存储

# dot_gitconfig.tmpl
[credential]
{{- if eq .chezmoi.os "darwin" }}
    helper = osxkeychain
{{- else }}
    helper = libsecret
{{- end }}

模板只表达真实的机器差异,不要为了炫技把简单配置写成复杂的条件树。

5. 敏感信息分级管理

不同敏感程度的信息适合不同的保护方式:

级别类型示例推荐方案
低敏感偏好设置、颜色主题、别名直接进 Git 仓库
中敏感邮箱地址、工作路径、可选功能开关模板变量 + 环境变量注入
高敏感API key、数据库密码、GitHub tokenage 加密 / 密码管理器
极敏感SSH 私钥、生产凭据不进 dotfiles,用专用密钥管理工具

age 加密

chezmoi 原生支持 age 加密,加密后的文件可安全提交到公开 Git 仓库,apply 时自动解密:

# 生成加密密钥
age-keygen -o ~/.config/chezmoi/age.txt
 
# 在 chezmoi.toml 中配置
# [age]
# identity = "~/.config/chezmoi/age.txt"
# recipients = ["<公钥>"]
 
# 加密文件纳入管理
chezmoi add --encrypt ~/.config/api-keys.env

环境变量注入

敏感信息不存文件,通过机器本地的 ~/.zshenv 或操作系统的 Secret 存储注入:

# ~/.zshenv(不进 dotfiles 仓库)
export GITHUB_TOKEN="ghp_..."
export OPENAI_API_KEY="sk-..."

.zshrc 模板中引用时,如果变量不存在就跳过加载:

# 仅在 token 存在时才配置 gh 工具
[[ -n "$GITHUB_TOKEN" ]] && gh config set oauth_token "$GITHUB_TOKEN"

密码管理器集成

chezmoi 支持 1Password、Bitwarden、Vault 等:

{{ (onepasswordRead "op://Personal/GitHub/token") }}
{{ (bitwarden "item" "GitHub Token").login.password }}

适合团队统一使用密码管理器的场景,不需要本地明文文件。

6. 边界原则

该进 dotfiles 的

  • Shell 配置:.zshrc.bash_profile.zshenv
  • 编辑器配置:~/.config/nvim/.vimrc
  • Git 配置:.gitconfig.gitignore_global
  • 终端配置:.tmux.confstarship.tomlsheldon.toml、终端主题
  • 开发工具配置:.config/gh/.config/atuin/

不该进 dotfiles 的

  • 缓存文件:~/.cache/node_modules/__pycache__/
  • 机器生成文件:.zsh_history(用 Atuin 管理)、~/.local/state/
  • SSH 私钥(~/.ssh/id_ed25519):不进公开仓库,即使加密也要慎重
  • 公司内网专用配置:隔离在机器本地,不推到个人公开仓库
  • 未加密的 token 和密码:直接存进 Git 就是在裸奔

维护原则

先稳,再全:先把 .zshrc.gitconfig、编辑器配置这三类纳入管理,把新机器恢复流程跑通,再逐步扩展。

每次 apply 前先 diffchezmoi diff 是安全边界。配置管理工具能批量写入家目录,必须先看它准备改什么,再执行。

敏感信息不靠记忆:能用密码管理器就不要手动 export;能用 age 加密就不要排除在外靠记忆重建。配置的可恢复性包含敏感信息的可恢复性。

dotfiles 的目标不是让每台机器变成同一台机器,而是让环境变化可理解、可恢复、可撤销。公共基础配置一致,机器差异显式,敏感信息隔离,部署前能看 diff——这比”完全一致”更实际,也更安全。