Chiffrement des disques (LUKS)
Un hôte chiffré (volume LUKS2 déclaré dans sa configuration disko) protège ses données en cas de vol ou de mise au rebut, mais réclame une passphrase à chaque démarrage. DNF industrialise ce point de friction avec deux garanties :
- plusieurs moyens de déverrouillage coexistent en permanence, la perte d’un moyen (passphrase oubliée, YubiKey égarée) n’enferme jamais dehors ;
- le prompt du boot se répond à distance, depuis le poste d’administration, sans écran ni clavier branchés sur l’hôte, et cela dès le tout premier démarrage qui suit l’installation.
Les moyens de déverrouillage
Section intitulée « Les moyens de déverrouillage »Chaque moyen occupe son propre keyslot dans l’en-tête LUKS2. Tous sont valables en même temps, sur chaque volume chiffré de l’hôte.
| Moyen | Où il vit | Rôle |
|---|---|---|
| Passphrase partagée | sops → luks-passphrase | Une seule pour tout le parc, autorise la gestion des keyslots. C’est aussi elle qui formate le disque |
| Passphrase par hôte | sops → luks/<hôte>/passphrase | À confier à l’utilisateur de la machine sans exposer le parc |
| YubiKeys FIDO2 | Dérivé de la clé physique | Toucher la clé au boot, rien à taper |
Provisionner un hôte
Section intitulée « Provisionner un hôte »just luks <hôte> # provisionne (ou converge) le chiffrementjust luks <hôte> pre # moitié hors ligne, sans toucher à la machinejust luks <hôte> passwd # fait tourner la passphrase par hôtejust luks <hôte> show # audit : table des keyslots + conformitéjust luks <hôte> '' <ip> # cible une IP explicite (hôte pas encore résolu)La recette est idempotente : chaque exécution converge et ne demande que ce qui manque. Elle est appelée automatiquement à deux moments, et il est rare d’avoir à la lancer soi-même :
| Appelée par | Action | Ce qu’elle fait |
|---|---|---|
just install <hôte> | pre | Avant le build, donc avant l’installation |
just install-here <hôte> | pre, sans compte nix (bootstrap-keys) | Premier poste, depuis l’ISO |
just configure <hôte> | (défaut) | Après le premier démarrage |
Sans volume LUKS dans le disko, c’est un no-op journalisé.
La phase pre ne touche jamais la machine. Elle prépare ce qui doit
exister avant que le système ne soit construit :
- la passphrase partagée dans sops si absente (demandée une seule fois pour tout le parc) ;
- la passphrase par hôte dans sops si absente, générée au hasard et sans rien demander (voir l’encadré ci-dessous) ;
- la clé d’hôte SSH de l’initrd, générée localement et rangée dans sops
(
luks/<hôte>/initrd-key, encodée en base64) ; - l’inscription de l’hôte dans le manifeste public
usr/secrets/luks.json(versionné en clair, il ne contient aucun secret) : c’est cette entrée qui active le module.
La phase par défaut ajoute ce qui demande la machine :
- repose la clé d’initrd depuis sops si elle manque sur la cible (elle n’en régénère jamais une nouvelle, cela invaliderait celle qu’a posée l’installation) ;
- sur une passerelle, relève l’IP WAN courante dans le manifeste
(repli de
just unlock, voir plus bas), à relancer si le fournisseur d’accès renumérote ; - si aucune passphrase gérée ne déverrouille le volume (hôte installé avant la bascule vers le formatage partagé), demande sa passphrase d’installation une dernière fois et enrôle la partagée avec.
Puis committer et déployer :
git add usr/secrets/luks.jsonjust commit "system(luks): <hôte>"just apply <hôte>Au déploiement, deux services idempotents convergent l’en-tête LUKS à chaque
apply : luks-passphrase-sync (passphrases partagée et par hôte) et
yubikey-luks-enroll (une entrée FIDO2 par YubiKey enrôlée sur le parc, voir
Authentification forte).
Rotation des passphrases
Section intitulée « Rotation des passphrases »- Par hôte :
just luks <hôte> passwd, puis commit et apply. L’ancien keyslot est supprimé et remplacé au déploiement suivant. - Partagée : modifier
luks-passphraseviajust sops, puis apply sur tout le parc — chaque hôte chiffré fait tourner son keyslot au passage.
Le service de synchronisation détecte les changements grâce à un registre
local (/var/lib/luks-passphrase/ledger) : une valeur sops modifiée
enrôle la nouvelle passphrase puis tue l’ancien slot. Les slots absents du
registre (FIDO2, enrôlements manuels) ne sont jamais touchés.
Déverrouiller au démarrage
Section intitulée « Déverrouiller au démarrage »Tout hôte chiffré suit la même séquence, sans rien à régler :
- YubiKey — une clé enrôlée et branchée fait clignoter sa diode : la toucher ouvre le volume, rien à taper. Aucune clé branchée, l’étape dure ~6 s ; une clé que personne ne touche, ~30 s (limite du firmware).
- Passphrase — une invite est ensuite posée, sans limite de temps. Elle accepte la passphrase par hôte, la partagée ou celle d’installation.
L’invite de l’étape 2 est une seule et même demande, servie en parallèle
sur la console physique (/dev/tty1) et par ssh sur le port 2222. Rien à
choisir, aucune fenêtre à rater : le premier qui répond ouvre le volume.
À distance, l’initrd démarre un sshd dédié sur le port 2222, avec sa
propre clé d’hôte persistante, accessible uniquement avec la clé de
déploiement nix. just unlock y répond :
just unlock <hôte> # passphrase lue dans sops, sinon demandée au terminaljust unlock attend que le port 2222 apparaisse (un point par tentative), lit
la passphrase partagée dans sops et la pousse dans l’initrd, puis vérifie
que la machine a bien quitté son initrd avant d’annoncer un succès. Si elle est
refusée, il réessaie avec la passphrase par hôte. C’est ce que
just full-install appelle tout seul après le premier redémarrage. Sur un hôte
non chiffré, c’est un no-op journalisé.
Aucune passphrase stockée acceptée, ou pas de clé d’infrastructure sur le
poste : depuis un terminal, just unlock présente le prompt LUKS via
systemd-tty-ask-password-agent. Il sonde le 2222 sur l’IP explicite (si
fournie), le nom d’hôte, puis l’IP WAN enregistrée dans le manifeste. Dans
les deux cas, la passphrase acceptée, le démarrage continue et le port 22 revient.
Vérifier un hôte
Section intitulée « Vérifier un hôte »just luks <hôte> show n’écrit rien : il interroge la machine et rend
compte. Il sort en erreur dès qu’un contrôle échoue, donc il s’utilise aussi
dans un script.
just luks <hôte> showUn premier bloc dresse la table des keyslots de chaque volume. Rien n’y est supposé : chaque passphrase gérée est réellement essayée contre l’en-tête, donc la colonne « Check » dit ce que le volume accepte aujourd’hui, pas ce qu’un registre a mémorisé.
/dev/disk/by-partlabel/disk-main-luks Slot Content Source Check ---- ------------------- --------------------------- ----------------- 0 Shared passphrase sops luks-passphrase opens the volume 1 Host passphrase sops luks/poste/passphrase opens the volume 2 YubiKey alice/main systemd-fido2 token enrolled 7 Unknown - not managed by DNF Slots in use: 4/32Un second bloc audite le déverrouillage distant, point par point :
| Contrôle | Ce qu’il attrape |
|---|---|
Hôte présent dans luks.json | Le module resterait inerte |
| Clé d’initrd sur la cible (+ empreinte) | Prochain apply sans déverrouillage distant |
| Sauvegarde sops de même empreinte | Une réinstallation perdrait l’accès distant |
| sshd d’initrd activé dans la configuration | nix.pub manquant, ou hôte hors manifeste |
| Chargeur d’amorçage postérieur à la clé | Le piège : clé absente de l’initrd qui démarre |
| Pilotes des cartes filaires présents dans l’initrd | Pas de réseau en stage 1 : rien ne répond sur 2222 |
| Système démarré = configuration auditée | Un apply en attente rendrait l’audit trompeur |
| IP WAN relevée (passerelles) | Injoignable en initrd une fois le VPN tombé |
Sous le capot
Section intitulée « Sous le capot »| Emplacement | Contenu | Statut |
|---|---|---|
usr/secrets/luks.json | Manifeste des hôtes provisionnés + IP WAN des passerelles | Public, versionné |
secrets.yaml → luks-passphrase | Passphrase partagée du parc | Chiffré sops |
secrets.yaml → luks/<hôte>/passphrase | Passphrase par hôte | Chiffré sops |
secrets.yaml → luks/<hôte>/initrd-key | Clé d’hôte SSH de l’initrd (base64) | Chiffré sops |
/var/lib/luks-initrd/ (cible) | Copie de travail de la clé d’initrd | Persistant, hors dépôt |
/var/lib/luks-passphrase/ledger (cible) | Registre des keyslots gérés (détection des rotations) | Persistant, hors dépôt |
Le module expose deux options : darkone.system.luks.enable (défaut true)
et darkone.system.luks.sshPort (défaut 2222).
Voir aussi
Section intitulée « Voir aussi »- Authentification forte (YubiKey) : l’enrôlement des clés physiques, dont le volet LUKS FIDO2
- Gestion des secrets : sops, clés age et rotation
- Le Justfile : la référence des recettes
luks,enteretconfigure