Gestion des dotfiles et des secrets avec chezmoi
Régulièrement il nous arrive d’avoir à re-configurer une nouvelle machine, avec
notamment la re-configuration des fichiers du $HOME
. Il y a plusieurs approches
et outils, faire une simple archive, utiliser git pour le répertoire $HOME,
utiliser des outils comme GNU stow, etc.
Ces approches ont des avantages et des inconvénients, mais je souhaitais
une fonctionnalité en particulier que chezmoi
vantait : l’intégration avec un gestionnaire de mot de passe.
chezmoi
dispose également d’autres fonctionnalités pour aider au bootstrap d’une
nouvelle machine comme le templating, et la possibilité de lancer des scripts de
configuration.
Dans cet article je me contenterai toutefois du management de dotfiles et des secrets.
Une fois chezmoi
installé, il faut l’initialiser
❯ chezmoi init
Cette commande créé un répertoire ~/.local/share/chezmoi
dans lequel les seront ajouté
les dotfiles géré par chezmoi
, ce dossier est un repo git, (mais il est possible
d’utiliser mercurial). Ce dossier et les fichiers dedans seront mentionné en temps que
fichiers source, tandis que les fichiers dans le dossier home seront mentionnés en
tant que fichiers cible (target).
Les bases
Maintenant ajoutons les fichiers qui nous tiennent à coeur, e.g.
❯ chezmoi add .zshrc
❯ chezmoi add .config/alacritty/alacritty.yml
❯ chezmoi add .SpaceVim.d/init.toml
Puis une fois tous les fichiers ajoutés, il faut aller dans le dossier de chezmoi
pour les ajouter au repo git.
❯ 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="Initial dotfiles config"
Bien entendu ce repo peut/doit être synchronisé avec un repo distant.
Gérer les changements
Supposons que le fichier $HOME/.zshrc
évolue, tel que l’ajout d’un plugin
oh-my-zsh, pour voir les différences entre
le fichier local (la cible) et le fichier source géré par chezmoi
, il faut
exécuter la commande chezmoi diff
:
❯ 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
- Les lignes commençant par un moins
-
viennent des fichiers cible (target), c’est-à-dire les fichiers du répertoire$HOME
. - Les lignes commençant par un plus
+
viennent des fichiers source, c’est-à-dire les fichiers du répertoire interne dechezmoi
.
Sachant interpreter la sortie de cette commande, dans l’exemple au-dessus, le fichier source
pnt uniquement le plugin man
alors que le fichier actuel déclare les plugins man osx
sur
cette ligne.
Maintenant regardons la sortie de deux autres commandes :
-
la commande
chezmoi apply
applique les sources sur les cibles locales, par exemple le fichier.zshrc
va converger vers ce qui existe dans le fichier source, donc une foischezmoi apply
exécuté, ce fichier ne déclarera que le pluginman
.❯ 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
-
la commande
chezmoi add
fera le contraire, elle applique les fichiers cible sur les fichiers sources, dans cet exemple ce sont les fichiers sources qui vont converger vers le contenu fichier.zshrc
du répertoire$HOME
, donc une foischezmoi add
exécuté, les fichiers source déclareront les pluginsman osx
.❯ 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
Notons que cette fois-ci les signes plus
+
et moins-
sont également en sens contraire.
Gestion des secrets avec 1Password
Maintenant que nous avons les bases de chezmoi
nous pouvons regarder comment gérer
les secrets. Avoir un repository distant privé pour ses dotfiles, c’est bien, mais
je souhaite tout de même garder ces fichiers protégés, en particulier si ces fichiers
doivent être stockés sur un repository distant, même s’il s’agit d’un repository privé.
C’est le moment d’utiliser le mécanisme de templating de chezmoi
et l’autil en ligne de
commande de mon gestionnaire de mot de passe, ici 1Password. Pour en savoir plus sur les
intégrations possibles il faut aller sur la guide how-to,
il y a notamment BitWarden, Keypassx et d’autres bien sûr.
Donc je voudrais en particulier mettre en sécurité certains fichiers des dossiers
.ssh
et .gnupg
.
❯ chezmoi add .ssh/id_rsa_home.pub
Pour SSH, id_rsa_home.pub
est la clef publique, il suffit d’utiliser les commandes
de base, en revanche ça devient intéressant pour id_rsa
qui est donc la clef privée.
❯ chezmoi add --template .ssh/id_rsa_home
❯ chezmoi add --template .ssh/config
❯ chezmoi add --template .gnupg/trustdb.gpg
❯ chezmoi add --template .gnupg/pubring.kbx
Je demande à chezmoi
de stocker id_rsa_home
et les autres fichiers sous forme
de template.
En ce qui concerne mes clefs GPG,
chezmoi
supporte GPG mais uniquement pour chiffrer des secrets pas pour stocker les secrets GPG. Bien qu’il y ait un mécanisme pour extraire les clefs secrètes en fichiers non binaires avec certaines commandesgpg
, et via les scripts run, cependant cette approche casse le modèle déclaratif dechezmoi
. Pour ces raisons j’ai choisi de sauver les fichiers binaires, ici uniquementtrustdb.gpg
etpubring.kbx
.
Lorsqu’il est stocké ce template a exactement le même contenu que l’orginal :
❯ chezmoi edit .ssh/id_rsa_home
# template is the same as the actual $HOME/.ssh/id_rsa_home
Il faut donc indiquer à chezmoi
comment le récupérer de 1Password. Mais
encore avant il faut entreposer ce fichier sur 1Password, il faut un
abonnement ce qui donne droit à un coffre-fort chez 1Password.
En premier il faut donc se connecter
❯ eval $(op signin my)
Puis il faut créer un document avec la commande 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"}
Bien évidement tous ces UUIDs ont été édité.
L’étape finale c’est de modifier les fichiers template. Étant donné qu’il y a
aussi des fichiers binaire vim
n’est pas particulièrement approprié pour les
modifier, du coup je m’y prends autrement :
❯ 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
Donc même le contenu des fichiers binaires .gnupg/trustdb.gpg
et .gnupg/pubring.kbx
sont remplacés par cette simple chaine de caractère {{- onepasswordDocument "uuid" -}}
.
Pour le moment 1Password ne supporte pas la mise à jour de documents, il faut supprimer
l’ancien avec son UUID puis ré-utiliser la sous commande create
avec la nouvelle
version du fichier, et mettre à jour le template avec le nouvel UUID.
Vérification des templates
Vu qu’il s’agit de template créé manuellement, une erreur est toujours possible. Autant vérifier le résultat de ces templates. Pour cela il faut appliquer les source sur un autre dossier cible.
❯ chezmoi apply --verbose --destination /Users/bric3/tmphome --dry-run
Une chose à noter, la commande ici est globale, et toutes les commandes globales qui ont besoin de 1Password vont demander à ce que la session 1Password en ligne de commande soit active, elle peut donc avoir en prérequis l’exécution de
eval $(op signin my)
.
Une fois près il suffit de retirer --dry-run
, et de voir le dossier tmphome
remplis (une fois la commande terminée car chezmoi
applique les changements
atomiquement).
❯ 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
Il est aussi possible de n’appliquer qu’une portion en spécifiant le chemin voulu
il faut en revanche le préciser avec un chemin absolu /Users/bric3/tmphome/.gnupg/
.
❯ chezmoi apply --verbose --destination /Users/bric3/tmphome /Users/bric3/tmphome/.gnupg/
Ce que nous voulions vérifier que le processing des templates donne exactement les même fichier que les originaux.
❯ 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 !
Pour finir
chezmoi
offre certaines fonctionnalités un peu plus engagées en particulier
pour les templates des scripts de bootstrap/configuration. Étant donné que
je n’utilise pas encore ça je le mets de côté.
Maintenant la seule chose que j’aurais à faire pour me re-configurer un home sera
❯ eval $(op signin my)
❯ chezmoi init --apply --verbose https://githost.tld/path/to/dotfiles.git
Également pour synchroniser les dotfiles depuis le repository upstream :
❯ eval $(op signin my)
❯ chezmoi source pull -- --rebase && chezmoi diff