Chezmoi - a very cool tool to manage your dotfiles
Posted on August 11, 2022 by Adrian Wyssmann ‐ 7 min read
Today, managing your dotfiles should be easy, so that you quickly can setup your environment and have it working as you would expect to. It all starts with a git-repo - with the benefit that you can share your files to others.
My first approach
Up to now, I had a very simple approach: Checkout files form a git-repo and create symlinks of the managed files. For the creation of the symlinks, I used stow - a manager for symlinks. I organized the files in a way, so that I have different “profiles” so I can have one for my personal environment and one for work. This script took care of the setup:
The approach is simple but has some drawbacks
- if you want to manage a file, you first have to move it from it’s original location to the checked our repo manually, so that you can create the symlink
- you have to be very carefully to not include private stuff - for that I had a separate, private repo in parallel
- the approach with “profiles” leads to potential duplication of a lot of content due to differences of private and work files, e.g.
user.mail
anduser.name
in.gitconfig
- environment specific config like proxy etc.
Why chezmoi?
It worked, but I never was very happy until I stumbled upon chezmoi which sounds very promising, what it offers and how it compares to other tools out there. Most importantly for me
- No bootstrap requirements
- Private and encrypted files
- Templating, which allows for machine-to-machine differences
- Windows support (yeah I have to use Windows sometimes)
So I decided to move from my original approach to chezmoi. The result can be found in dotfiles. I won’t go into details about how it works, as the official docu is very good and informative. But I want to describe what I did, and show how I solved some “problems” I consider important to me.
So what did I do?
Moving away from symlinks to files
I decided to use a new git-repo, as the structure of chezmoi is different. So I ran a chezmoi init
without specify a repo. chezmoi created an empty git repo under ~/.local/share/chezmoi
. As mentioned above, my approach relied on symlinks. So in order to [add] the files to chezmoi, using the --follow
flag - e.g. chezmoi add ~/.zshrc --follow
added the actual file as ~/.local/share/chezmoi/dot_zshrc
. The content in ~/.local/share/chezmoi
represents the state, whereas the naming of the files uses so called source state attributes.
I started to go trough all my dotfiles until I stumbled on .muttrc
which contains my mail information as well as passwords for the smtp access, I have two choices
- encrypt the whole file
- grab the password from my password manager, when state is applied
I decided to encrypt the whole file for now.
bootsrapping and encryption
While chezmoi does not have any requirements and installation is pretty easy, if you want to have encryption, you need either a gpg key or a passphrase. I decided to use a passphrase rather than a gpg-key, which skips the manual distribution of the gpg-key - cause as far as I have seen you have to use the same key on all machines. As I am lazy, I don’t want to enter the passphrase for each operation. Luckily the documentation provides an easy way to create the chezmoi.toml config file upon initialization:
If a file called
.chezmoi.$FORMAT.tmpl
exists thenchezmoi init
will use it to create an initial
Hence, I created the following .chezmoi.toml.tmpl
which not only stores then passphrase, but also other machine specific data:
While passphrase
is used in the same config file, email
, username
and signkey
are used to populate the .gitconfig
file, using [templating][templates]-mechanism. So there is a file called dot_gitconfig.tmpl
which contains the generic git stuff (aliases, etc) which I use on all machines, but with machine-specific instructions to add the variables from above:
As the encryption is setup now, I can easilly add ~/.muttrc
encrypted by running chezmoi add --encrypt ~/.muttrc
. which will add encrypted_dot_muttrc.asc
to the state:
Add my scripts
I have an additional repo with shell-scripts, which contains two folders:
- nautilus - Scripts which can be executed in Gnome’s file manager Nautilus
- scripts - arbitrary shell scripts
The folders shall be mapped as follows:
scripts
to~ /.local/bin
nautilus
to~/.local/share/nautilus/
As chezmoi allows include files from elsewhere, I decided to use this feature. First I added .chezmoiexternal.toml
with the following content:
This checks out the repo to ~/.local/scripts
. But how shall I map the subfolders as expected? Well also here chezmoi helps, as it offers a feature, that use scripts to perform actions. So I created a file run_once_nautilus_scripts.sh.tmpl
which takes care of creating the necessary symlinks:
How to use it
As described here there are some simple commands to execute:
Pull the changes from your repo and apply them in a single command
If you want to see the changes before applying
Apply changes
If you want to install chezmoi and your dotfiles on a new machine with a single command, run this:
For setting up transitory environments (e.g. short-lived Linux containers) you can install chezmoi, install your dotfiles, and then remove all traces of chezmoi, including the source directory and chezmoi’s configuration directory
Conclusion
chezmoi is a undoubtedly very cool to manage your dotfiles and as you can see very flexible. It’s also very easy to use. Once I am back at work, I will also migrate my work-files to it, so I have a single source of truth.
Btw. if you are using navi, you can find here my cheatsheet for chezmoi.