Dotfile-Management-III
Dotfiles managed with chezmoi
Every once in a while, you may need to bootstrap a new machine, and along with it to reconfigure home directory’s dot files. Various approaches already exist, using simple archive, git the home directory, gnu stow (symlinks), etc.
These approaches work more or less depending on your expectation, I
wanted something that chezmoi
touts: the integration with password managers. There are other
features on the shelf too, like templating, and system bootstrap
facility.
Here I will only focus on the management of the dot files and of the secrets.
After you’ve got chezmoi
installed, you need to
initialize it
❯ chezmoi init
This will create a directory there ~/.local/share/chezmoi
and managed
dotfiles will land here, this folder is actually a git repository. This
folder and the files in here are referred to as the source files while
the files in the home directory adn are referred to as the target.
The basics
Then start adding the files you care about, e.g.
❯ chezmoi add .zshrc ❯ chezmoi add .config/alacritty/alacritty.yml ❯ chezmoi add .SpaceVim.d/init.toml
Then when ready commit the files, for that you need to go to the
source directory of chezmoi
and perform the git dance.
❯ chezmoi cd ❯ git st On branch master No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) dot_SpaceVim.d/autoload/myspacevim.vim dot_SpaceVim.d/init.toml dot_config/alacritty/alacritty.yml dot_config/iterm/com.googlecode.iterm2.plist dot_config/starship.toml dot_config/topgrade.toml dot_gitconfig dot_gitignore-global dot_gradle/init.d/checknetwork.gradle dot_gradle/init.d/tasktree.gradle dot_mrconfig dot_p10k.zsh dot_zshrc ❯ git add * ❯ git commit --message="Init config"
This repository can then be synchronized with a remote git repository.
Managing changes
Suppose the file $HOME/.zshrc
evolves a bit, like declaring another
oh-my-zsh plugin, in order to
see the difference between actual files, and the files that are backed
up by chezmoi
use the chezmoi diff
command
❯ chezmoi diff
install -m 644 /dev/null /Users/bric3/.zshrc
--- a/Users/bric3/.zshrc
+++ b/Users/bric3/.zshrc
@@ -85,7 +85,7 @@
gitfast
git-extras
- man osx
+ man
gradle mvn
kubectl helm docker
- The lines starting with a minus
-
comes from the target files, i.e. the files in the$HOME
directory. - The lines starting with a plus
+
comes from the source files, i.e. the files in thechezmoi
internal directory.
Knowing the above, this output can be understood as, the source file
only have the man
plugin entry on that line, while the local file have
man osx
plugin entries on that same line.
Now let’s look at the output of two other commands:
chezmoi apply
will apply the source file to their local target, e.g. the.zshrc
file will converge to what’s in the source file, oncechezmoi apply
has been executed, this file will only declare theman
plugin.❯ chezmoi apply --verbose --dry-run ~/.zshrc install -m 644 /dev/null /Users/bric3/.zshrc --- a/Users/bric3/.zshrc +++ b/Users/bric3/.zshrc @@ -85,7 +85,7 @@ gitfast git-extras - man osx + man gradle mvn kubectl helm docker
chezmoi add
will do the opposite, it will change the source file.zshrc
from the local target file, i.e. after executingchezmoi add
, the source file will now have theman osx
entries.❯ chezmoi add --verbose --dry-run ~/.zshrc rm -rf /Users/bric3/.local/share/chezmoi/dot_zshrc install -m 644 /dev/null /Users/bric3/.local/share/chezmoi/dot_zshrc --- a/Users/bric3/.local/share/chezmoi/dot_zshrc +++ b/Users/bric3/.local/share/chezmoi/dot_zshrc @@ -85,7 +85,7 @@ gitfast git-extras - man + man osx gradle mvn kubectl helm docker
Note hoe the minus
-
and plus+
appears in the opposite change.
Handling secret with 1Password
So now that we have a basic setup and understanding of the tool, let’s manage files with secrets. Currently, I have some files that I’d rather keep protected, especially if I use a private repository on my git host be it GitHub, Gitlab or else.
For that we’ll need the chezmoi
templating feature, and the cli tool
from the password manager, in this blog post I’m using on 1Password, but
check the
how-to
documentation for other password manager support like Bitwarden or
Keypassx.
So I especially need to store securely files in my .ssh
folder and my
.gnupg
folders.
❯ chezmoi add .ssh/id_rsa_home.pub
Regarding SSH, id_rsa_home.pub
is a public key, so I’m just adding it
raw, however things get interesting for id_rsa
which is my private
key.
❯ chezmoi add --template .ssh/id_rsa_home ❯ chezmoi add --template .ssh/config ❯ chezmoi add --template .gnupg/trustdb.gpg ❯ chezmoi add --template .gnupg/pubring.kbx
Here I’m telling chezmoi
to store id_rsa_home
as a template. While
the stored file template still contains the original:
Regarding GPG files,
chezmoi
supports GPG, but it’s used as way to encrypt secrets not to backup the GPG secrets. There’s indeed a way to extract these secret keys as non-binary files using a fewgpg
commands, via run scripts, however this break the declarative approach ofchezmoi
. So I chose to save the binary files, here onlytrustdb.gpg
andpubring.kbx
.
❯ chezmoi edit .ssh/id_rsa_home # template is the same as the actual $HOME/.ssh/id_rsa_home
In order to tell make chezmoi
aware of 1Password for this template, I
first need to store the documents on 1Password. For that it is necessary
to have a 1Password subscription that lets you have an online vault.
First sign-in
❯ eval $(op signin my)
Then store documents using the 1Password cli tool op
❯ op create document .ssh/id_rsa --tags chezmoi --title .ssh/id_rsa {"uuid":"ti2adie9Aixaidae4dahpoh5io","createdAt":"2020-04-01T17:53:49.596484+02:00","updatedAt":"2020-04-01T17:53:49.596484+02:00","vaultUuid":"eith2iequievuthae9Eedaiboh"} ❯ op create document .ssh/config --tags chezmoi --title .ssh/config {"uuid":"pairahnietaluv5Moonahm2ea5","createdAt":"2020-04-01T17:54:36.402265+02:00","updatedAt":"2020-04-01T17:54:36.402265+02:00","vaultUuid":"eith2iequievuthae9Eedaiboh"} ❯ op create document .gnupg/trustdb.gpg --tags chezmoi --title .gnupg/trustdb.gpg {"uuid":"zi8ieleiphieTithiep2xieg3u","createdAt":"2020-04-01T17:57:13.338949+02:00","updatedAt":"2020-04-01T17:57:13.338949+02:00","vaultUuid":"eith2iequievuthae9Eedaiboh"} ❯ op create document .gnupg/trustdb.gpg --tags chezmoi --title .gnupg/pubring.kbx {"uuid":"losachuYeeho5Eiph2uzoquohl","createdAt":"2020-04-01T17:58:12.818754+02:00","updatedAt":"2020-04-01T17:58:12.818755+02:00","vaultUuid":"eith2iequievuthae9Eedaiboh"}
All UUIDs have been edited of course.
To complete this operation, we need to modify the templates files where
to get the file, since there’s a few binary files vim
is not suited
for that, so I’m using another mean to replace the content by the
template.
❯ chezmoi cd ❯ echo -n '{{- onepasswordDocument "ti2adie9Aixaidae4dahpoh5io" -}}' > private_dot_gnupg/private_id_rsa.tmpl ❯ echo -n '{{- onepasswordDocument "pairahnietaluv5Moonahm2ea5" -}}' > private_dot_gnupg/config.tmpl ❯ echo -n '{{- onepasswordDocument "zi8ieleiphieTithiep2xieg3u" -}}' > private_dot_gnupg/private_trustdb.gpg.tmpl ❯ echo -n '{{- onepasswordDocument "losachuYeeho5Eiph2uzoquohl" -}}' > private_dot_gnupg/private_pubring.kbx.tmpl ❯ exit
Note that I’m replacing the binary file content of .gnupg/trustdb.gpg
and .gnupg/pubring.kbx
with the template character string
{{- onepasswordDocument "uuid" -}}
.
Also, one downside with 1Password at this time, is that documents cannot
be updated, you need to remove the old document using the UUID and use
the create
sub-command on the new version of the file, you’ll get a
new uuid and as such you’ll have to update these template
Checking the templates
Eventually it’s possible to check the templating works by apply the source files to another target directory.
❯ chezmoi apply --verbose --destination /Users/bric3/tmphome --dry-run
One thing you may notice is that now, this is global command, and all global command will require the 1Password
op
session to be active, and you may have to run againeval $(op signin my)
as a pre-requisite.
If ready remove the --dry-run
, and see the tmphome
folder populated
(after the command has run because chezmoi
applies changes
atomically).
❯ l /Users/bric3/tmphome Permissions Size User Date Modified Name drwxr-xr-x - bric3 2 Apr 2:54 .config .rw-r--r-- 3.1k bric3 2 Apr 2:54 .gitconfig .rw-r--r-- 2.4k bric3 2 Apr 2:54 .gitignore-global drwx------ - bric3 2 Apr 2:55 .gnupg drwxr-xr-x - bric3 2 Apr 2:55 .gradle drwxr-xr-x - bric3 2 Apr 2:55 .kube .rw-r--r-- 7.5k bric3 2 Apr 2:55 .mrconfig .rw-r--r-- 51k bric3 2 Apr 2:55 .p10k.zsh drwxr-xr-x - bric3 2 Apr 2:54 .SpaceVim.d drwx------ - bric3 2 Apr 2:56 .ssh .rw-r--r-- 7.4k bric3 2 Apr 2:56 .zshrc
Note, it’s possible to apply only a portion of the dot files in that
temporary folder just by adding the target absolute path
/Users/bric3/tmphome/.gnupg/
❯ chezmoi apply --verbose --destination /Users/bric3/tmphome /Users/bric3/tmphome/.gnupg/
And what we wanted, make sure the templates are exactly the same as the original files
❯ b3sum /Users/bric3/tmphome/.gnupg/pubring.kbx /Users/bric3/.gnupg/pubring.kbx 1b51813215edef2e97846bfee51cd02dd8d6c2cb6a119b3681ac087597fb0197 /Users/bric3/tmphome/.gnupg/pubring.kbx 1b51813215edef2e97846bfee51cd02dd8d6c2cb6a119b3681ac087597fb0197 /Users/bric3/.gnupg/pubring.kbx ❯ b3sum /Users/bric3/tmphome/.gnupg/trustdb.gpg /Users/bric3/.gnupg/trustdb.gpg d2c67bb808b223cc6f1b7c95b627b4b5551daa1312e12dd0ad3c5bfa1ac35dc9 /Users/bric3/tmphome/.gnupg/trustdb.gpg d2c67bb808b223cc6f1b7c95b627b4b5551daa1312e12dd0ad3c5bfa1ac35dc9 /Users/bric3/.gnupg/trustdb.gpg
Looks good !
It’s not over
chezmoi
comes with some features that are a bit more involved,
especially the templating and the system bootstrap/configuration. As I’m
not using them for now I’ll leave it aside.
Now the only thing I’ll need to get my dotfiles is
❯ eval $(op signin my) ❯ chezmoi init --apply --verbose https://githost.tld/path/to/dotfiles.git
Additionally, in order to synchronize the dotfiles from upstream repository :
❯ eval $(op signin my) ❯ chezmoi source pull -- --rebase && chezmoi diff
🔗 Home | 🔗 posts |