Chezmore Chezmoi
In a previous article, I briefly touched on the idea of using chezmoi
to manage syncing my zsh settings across machines. This has worked pretty well, but there were things that I still needed to do manually on each machine that I wanted to keep in sync. This is, naturally, something that gets the grumps going - we should be able to automate this! So, rolling up my sleeves for the New Year, I dug a bit further into chezmoi
to see what could be done about it.
What Are You Doing?⌗
To start with, let’s take a look at what chezmoi
is managing for us:
>>> chezmoi managed
.gitconfig
.zshrc
OK, so nothing too surprising here. It’s already worked out that my ZSH and git configs need to be synced. But we’d like to try managing some non-dotfiles as well. How can we go about this? The online manual isn’t hugely helpful here - although there is a section on managing different types of file, it doesn’t really tell you how to do that! (although it does give us a few hints as to some of the other things that it can do.) So, let’s turn to old faithful:
chezmoi --help
>>> chezmoi --help
Manage your dotfiles across multiple diverse machines, securely
Usage:
chezmoi [command]
Available Commands:
add Add an existing file, directory, or symlink to the source state
...
So, the first command ends up sounding pretty close to what we want to do. Let’s give it a go! We’ve got a folder for scripts and other things called $HOME/bin, so let’s try adding the script to install the various utilities I want to install on each machine to chezmoi
:
>>> chezmoi add bin/install_files.zsh
>>> chezmoi managed
.gitconfig
.zshrc
bin
bin/install_files.zsh
This looks promising! Let’s double-check that it’s all in the right place:
>>> chezmoi cd
>>> ls
bin dot_gitconfig dot_zshrc
>>> ls bin
executable_install_files.zsh
Nice! It’s tagged the shell script as an executable, and also ignored all the other various scripts I had in there, so it looks like it should happily merge these onto any target machine I choose. I went ahead and committed these to git, and all was mostly well in the world.
Managing Machine-Specific Settings⌗
The next funky feature that I found useful was the ability to have chezmoi
manage scripts with specific behaviour for different machines. This is all managed via the use of templates, which allow you to do something like the following (you can tell that the example is taken from the chezmoi template documentation, as I would rather gouge out my internal organs with a toothpick than use vi
):
# common config
export EDITOR=vi
# machine-specific configuration
{{- if eq .chezmoi.hostname "work-laptop" }}
# this will only be included in ~/.bashrc on work-laptop
{{- end }}
You can see that the example uses the hostname to drive this particular bit of config, but there’s a ton of other settings that can be used to drive the output:
>>> chezmoi data
{
"chezmoi": {
"arch": "amd64",
"commandDir": "/home/obfuscated",
"configFile": "/home/obfuscated/.config/chezmoi/chezmoi.toml",
"executable": "/home/obfuscated/bin/chezmoi",
"fqdnHostname": "MyNameGoesHere",
"hostname": "MyNameGoesHere",
"kernel": {
"osrelease": "5.15.0-91-generic",
"ostype": "Linux",
"version": "#101-Ubuntu SMP Tue Nov 14 13:30:08 UTC 2023"
},
"os": "linux",
"osRelease": {
"id": "linuxmint",
"idLike": "ubuntu debian",
"name": "Linux Mint",
"prettyName": "Linux Mint 21.2",
"privacyPolicyURL": "https://www.linuxmint.com/",
"supportURL": "https://forums.linuxmint.com/",
"ubuntuCodename": "jammy",
"version": "21.2 (Victoria)",
"versionCodename": "victoria",
"versionID": "21.2"
},
"pathListSeparator": ":",
"pathSeparator": "/",
"windowsVersion": {},
}
}
I’ve only included a few of the available options here, but as you can see, it’s pretty comprehensive. This makes it nice and easy to add per-machine settings with minimal fuss.
The only wrinkle here is that these are used with templates, while the dotfiles I was using weren’t templates as far as chezmoi
was concerned. Luckily, this is easy to fix:
>>> chezmoi chattr +template ~/.zshrc
>>> chezmoi cd
>>> ls -R
bin dot_gitconfig.tmpl dot_zshrc.tmpl
./bin:
executable_install_files.zsh.tmpl
>>> chezmoi managed
.gitconfig
.zshrc
bin
bin/install_files.zsht
This renames the file in your chezmoi folder to .tmpl to indicate that it’s a template now, but as far as chezmoi
is concerned, the same target files are being managed.
Templating is controlled via the Go text/template
syntax (with the sprig
extension applied), which is pretty powerful overall. I’ve moved the installation of Oh-My-Posh to be Linux-only, and have added some machine specific aliases to the template file too. When you do a chezmoi apply
, the template is applied and the output is written to the file being controlled.
Some Last Minute Touchups…⌗
At this stage, I’m nearly happy with everything. The last thing that I’ve tidied up isn’t quite a chezmoi
thing though. It’s the use of difftastic
for diffing in git (and other programs, like the Jetbrains IDEs I use). Although it’s still under development, it seems pretty spiffy so far. I added this to my binary installation script, then updated my .gitconfig to add the following:
[diff]
external = difft
This means that difftastic is now used by default for my git diff
output. Adding this into chezmoi
and syncing it across machines now means that I’ll have consistent diffing wherever I’m coding.
Eating Pudding⌗
Of course, the important part is testing that this all works OK across different machines. Deploying to my OMV
server worked just fine, but my Ubuntu-based laptop had a bit of weirdness, mainly due to a setting for Python that I hadn’t come across before. The 3.11 installation was marked as EXTERNALLY MANAGED, which means that you can’t by default install Python packages globally for a machine. This isn’t really a problem, all I had to do was make the Chezmoi template for binary installation work a bit differently on my laptop - which is exactly what the templates are for! And other than that minor wrinkle, it all worked just fine.
I now have a nicely synced terminal setup across the main Linux machines that I work on. I haven’t touched my Windows installation much since switching to Mint, so even though Chezmoi
supports Windows, I don’t see much point in making it work for that machine.
It took a little effort and more than a few grumps to get it all setup, but now that it is, I can easily switch between machines and have them all look and feel the same, which is a big win for my productivity. Not a bad start to 2024!