The problem
Every time, When I got a new Macbook / Linux Machine (an office work, a VPS), I end up spending hours setting up terminal from scratch. Installing
zsh, zinit
, git, configuring SSH keys, setting up plugins, aliases and shell functions…I tried solving this with a bootstrap script. It worked well enough, it installed everything:
brew, git, docker , etc. But installing programs is only half the battle. It didn't restore my configuration files. I still had to set up nvm, and redefine all my aliases and functions from scratch every time.With
GNU Stow, configuration files are simply symlinked, allowing immediate config updates. However, this introduces an annoying issue: authentication files for CLI tools like Claude Code and GitHub Copilot are also stored within the symlinked directories. Consequently, every time I push to Git, I am forced to review the changes to ensure no secrets are included. On several occasions, I have accidentally pushed these sensitive files to GitHub and had to reset those commits.The other pain point: when I updated a config on one machine, I had to manually mirror that change on all the others. If I forgot, the machines would quietly drift apart, and I'd end up with different behavior depending on where I was working
Introducing chezmoi
Chezmoi is an open-source tool managing your
dotfiles across multiple machine, securely.The concept is simple: you tell
chezmoi which config files to tack, and it stores them in a Git repository that you push to Github (or any remote). Frome there, syncing your config to a new machine is just a matter of cloning and applying.On a new machine, I either run the one line:
1chezmoi init --apply $GITHUB_USERNAME
2
3# or
4chezmoi init --apply https://github.com/$GITHUB_USERNAME/dotfilesOr after my bootstrap script install everything:
1chezmoi init
2chezmoi applyWhen I update a config on a config on one machine:
1chezmoi add ~/.zshrc
2chezmoi cd
3git commit -m 'chore: update zsh config'
4git pushAutomatically commit and push changes to your repo:
1[git]
2 autoCommit = true
3 autoPush = true~/.config/chezmoi/chezmoi.toml
On another machine will pull the latest changes from your repo
1chezmoi git pull -- --autostash --rebase && chezmoi diffIf you happy with changes, then you can run to apply them:
1chezmoi applyRestart the terminal and it’s done. This has been especially useful when spinning up AWS EC2 instances. What used to take hours now takes minutes.
Documentation: Dailly Operations - chezmoi
Architecture Design
Repository Structure
1├── ...
2│
3├── home/ # dotfiles under chezmoi management
4│ ├── dot_zshrc # - deployed as ~/.bashrc
5│ ├── dot_vimrc # - deployed as ~/.vimrc
6│ ├── dot_config/ # - deployed as ~/.config/
7│ └── .chezmoi.yaml.tmpl # - chezmoi configuration file
8│
9├── install/ # setup scripts (testable)
10│ ├── common/ # - common installation scripts
11│ ├── macos/ # - macOS-specific scripts
12│ └── ubuntu/ # - Ubuntu-specific scripts
13│
14├── tests/ # automated tests with Bats
15│ ├── install/ # - tests for installation scripts
16│ └── files/ # - tests for files after chezmoi deployment
17│
18└── ...I’m sure there are other ways to manage
dotfiles , but this is what’s been working for me. Let me known how you handle yours.