Tools I love: Chezmoi

Keywords: #tools #unix

I’ve done a bajillion things to manage my dotfiles over the years. I found chezmoi a few years back and have really stuck with it.

Chezmoi is an amazing tool for managing dotfiles. It lets me replicate my required config across a bunch of hosts. I’ve tried a variety of tools over the years. Handmade shell scripts, just cloning a git repo, or using Ansible.

Roll my Own

The shell scripts pre-date git, and mostly rolled up files, streamed them over ssh, and unfurled them. I managed them in rcs, then CVS, then Subversion. It was clunky and got crazy when I wanted to account for differences.

Git clone

I fell back to just pulling common stuff from git, but that kept me from managing those differences. I want my laptop to be different from what I deploy to servers. I need different settings on my personal machines than work.

You can’t just keep a .git in your home directory. Things start going nuts when you forget to git init a new project. You can accidentally create sub repos very quickly. So then you make a script or Makefile to install all the things.


So Ansible! Right? Templating! Looping and modules are good enough, right?

Oh my goodness. I love Ansible to roll out a config once or manage something that updates infrequently. But using it every time I tweak my vim config is so slow and cumbersome. And the role starts getting preeeety long.


So yeah. My point. I’ve been using chezmoi for some time. I love that it’s a go binary and brain dead easy to deploy. It does basically what I needed from the git clone method for me with all the kinks worked out. It handles templating gracefully with the standard go templating.

I bootstrap this on new hosts (say a Raspberry Pi or a new server I do stuff on at work) with an Ansible role that deploys the binary and does the basic setup.

I handle the home/vs work by looking at the domain. I deal with having fancy neovim (0.5+) on my laptops vs older vim/neovim on other machines with a git branch for the shiny.

The overhead

You do need to chezmoi edit any file and then chezmoi apply, or change the file and pull it back into the chezmoi config. But that’s really a pretty easy habit to develop. It is confusing sometimes when you want to use git command line arguments like git commit -am 'something'. But it’s just a matter of running chezmoi git commit -- -am 'something'.

The one negative

My one complaint is that the variables for templating have changed between versions. Something like fullHostname became fqdnHostname. And go doesn’t let you do things to check for if a variable exists do this, otherwise that.

My workaround

I don’t use native or Homebrew installs.

I build the binaries myself anyway for my arm systems since I have 32-bit and 64 and I like to compress the binaries for those tiny systems (downside to go binaries in general).

So I just build a consistent version for all the platforms I use:

  • Linux
    • x86_64
    • 32 bit ARM
    • 64 bit ARM
  • FreeBSD
    • x86_64
  • macos
    • x86_64
    • Maybe an M1 one day :).

Then I have Ansible deploy the appropriate one to ~/bin.

I get what I want where I want. I don’t update the version very frequently.


I get what I want. Shell profile changes, vim/neovim tweaks, managing different git configs for home and work.

I quickly rolled out switching my git config from using master to main as the default branch. (I like that change. Don’t @ me).

I can maintain a schnazzy lsp + lua neovim config and an old school vimscript config that works with neovim and vim easily just by changing the branch chezmoi is using on those special fancy hosts.

I don’t know if it’s useful to anyone else. But I thought I’d share since it’s not a “hey this is a new cool thing I found”, but a “hey, I’ve been doing this for ~3 years now and don’t see myself changing.”