TL;DR
Chezmoi follows a declarative approach to configuration management. Even if you already use a configuration-management system, you should check out how it compares!
A Custom Configuration Makes You Feel at Home
Your git aliases, shell setup, keyboard shortcuts and even your favorite fonts are tweaked for your own needs and tastes. It’s part of what makes your computer, your computer. All this configuration evolves over years and is slowly refined over time. It may actually be your longuest-living project.
Do you want to start from scratch when you switch computer? Of course not! And you wouldn’t want to break it with adventurous changes either! Versioning it in git backs up the history and eases the management of this important work. Configuration updates are also more convenient to share between machines this way.
Enter Chezmoi
In the git-based configuration management described above, how to account for the small variations (like between your work environment and personal computer)? Git supports conditional inclusion of configuration files, but how about the other tools? What if you want to encrypt your secrets in your config files, to publish your configuration on GitHub?
Chezmoi follows a declarative approach: it has a separate source repository1 to describe a target state, that then gets applied to your home directory. This is possible through templates, that are activated selectively for some files. The rest of this post shows how powerful templating can be.
Account for Variations Between Machines
Let’s start with a simple example. In the git configuration, you put your email, that’s then included in all your commits. Thus, you often want to have a different email in .gitconfig
for your work and personal profiles. To tackle this issue, I put the following in my .gitconfig
chezmoi template:
[user]
email = {{ .email }}
and it gets rendered to this:
[user]
email = me@my.home
on my personal computer and this:
[user]
email = me@my.work
on my work computer. It serves a purpose similar to conditionally setting your gitconfig, but it is applicable to any program.
Even More Variations with Templates
Now, let’s cover a more powerful use of templates.
You can have multiple files generated from one using “global” templates. For instance, if you use i3 and sway as your windows manager, you likely have slightly different configurations, given that sway’s configuration is mostly compatible with that of i3. To keep everything in one file, while taking advantages of sway-specific features, you can (in your chezmoi repository):
- Put your configuration in
.chezmoitemplates/sway_i3
. You can keep any sway specific section in a templatedif
statement, like so:{{- if eq .f "sway" }} # Sway specific stuff here, like output configuration {{- end }}
- In
dot_config/i3/config.tmpl
(anddot_config/sway/config.tmpl
), use something like:
As you may have noticed, chezmoi renames some files in the source state, to encode parameters and for readability. So{{/* Environment */}} {{- $env := . -}} {{/* Flavor */}} {{- $f := "i3" -}} # <--- Change this to "sway" in dot_config/sway/config.tmpl {{- template "sway_i3" dict "f" $f "env" $env -}}
dot_config/sway/config.tmpl
becomes.config/sway/config
(.tmpl
means the file is executed as a template).
Also,$env
is used to keep the general template context, for instance to check the OS version in our template config file.
.chezmoiignore
Finally, chezmoi supports an ignore file named .chezmoiignore
. The concept is similar to the well known .gitignore
: patterns listed in this file are ignored by chezmoi. In other words, some files are stored in your chezmoi repository, but do not reflect in your home. This can be used if you put a README.md
in your configuration repository, as you don’t want this file in your home directory. Just write:
README.md
in .chezmoiignore
and the README.md
won’t be copied in your home.
You can do more advanced things with .chezmoiignore
as it is a template by default. From the documentation:
{{- if ne .email "firstname.lastname@company.com" }}
# Ignore .company-directory unless configured with a company email
.company-directory # note that the pattern is not dot_company-directory
{{- end }}
Conclusion
Chezmoi has lot more features, like encryption or installation in GitHub Codespaces. It is quite well documented, in particular with a quick start guide.
I’ve switched to it almost two years ago, I don’t regret it at all!
Bonus: Vim Snippet
To update the target state automatically when editing the source file in the chezmoi repo, I use this vim snippet (with the fish shell):
autocmd BufWritePost ~/.local/share/chezmoi/* ! chezmoi apply --source-path %; or for f in (rg -l 'template "%:t"'); chezmoi apply --source-path $f; end
You should store this source repository in a git repository to easily revert changes and share configuration update between various machines. ↩︎
Liked this post? Subscribe:
Discussions
This blog does not host comments, but you can reply via email or participate in one of the discussions below: