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$HOMEdirectory. - The lines starting with a plus
+comes from the source files, i.e. the files in thechezmoiinternal 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 applywill apply the source file to their local target, e.g. the.zshrcfile will converge to what’s in the source file, oncechezmoi applyhas been executed, this file will only declare themanplugin.❯ 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 dockerchezmoi addwill do the opposite, it will change the source file.zshrcfrom the local target file, i.e. after executingchezmoi add, the source file will now have theman osxentries.❯ 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,
chezmoisupports 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 fewgpgcommands, via run scripts, however this break the declarative approach ofchezmoi. So I chose to save the binary files, here onlytrustdb.gpgandpubring.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
opsession 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 |