Aller au contenu

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.

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.

MoyenOù il vitRôle
Passphrase d’installationMémoire de l’admin (saisie à l’install disko)Filet ultime, jamais touchée par DNF
Passphrase partagéesops → luks-passphraseUne seule pour tout le parc ; autorise la gestion des keyslots
Passphrase par hôtesops → luks/<hôte>/passphraseÀ confier à l’utilisateur de la machine sans exposer le parc
YubiKeys FIDO2Dérivé de la clé physiqueToucher la clé au boot, rien à taper
Fenêtre de terminal
just luks <hôte> # provisionne (ou converge) le chiffrement
just luks <hôte> passwd # fait tourner la passphrase par hôte
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 d’ailleurs appelée automatiquement par just configure <hôte> (sans volume LUKS dans le disko, c’est un no-op journalisé). Dans l’ordre :

  1. crée la passphrase partagée dans sops si absente (demandée une seule fois pour tout le parc) ;
  2. crée la passphrase par hôte dans sops si absente (saisie vide = valeur aléatoire forte, l’hôte reste déverrouillable par la partagée et les YubiKeys) ;
  3. inscrit 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 ;
  4. génère sur la cible la clé d’hôte SSH de l’initrd (/var/lib/luks-initrd/ssh_host_ed25519_key, persistante) ;
  5. sur une passerelle, relève l’IP WAN courante dans le manifeste (repli de just enter, voir plus bas) — relancer la recette si le fournisseur d’accès renumérote ;
  6. si aucune passphrase gérée ne déverrouille encore le volume (hôte installé avec une autre passphrase), demande la passphrase d’installation une fois et enrôle la partagée avec.

Puis committer et déployer :

Fenêtre de terminal
git add usr/secrets/luks.json
just 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).

  • 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-passphrase via just 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 tue l’ancien slot et enrôle la nouvelle, sans jamais toucher au keyslot d’installation.

Sur place, deux gestes possibles devant la console :

  • YubiKey enrôlée branchée : toucher la clé quand la diode clignote (fido2-device=auto), rien à taper ;
  • au clavier : taper la passphrase par hôte, la partagée, ou celle d’installation.

À 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. Le point d’entrée reste le même qu’en temps normal :

Fenêtre de terminal
just reboot <hôte> # ou toute autre cause de redémarrage
just enter <hôte> # détecte l'attente en initrd et présente le prompt

Quand le port 22 ne répond pas, just enter sonde le port 2222 sur l’IP explicite (si fournie), le nom d’hôte, puis l’IP WAN enregistrée dans le manifeste, et répond au prompt LUKS via systemd-tty-ask-password-agent. La passphrase saisie, le démarrage continue et le port 22 revient.

EmplacementContenuStatut
usr/secrets/luks.jsonManifeste des hôtes provisionnés + IP WAN des passerellesPublic, versionné
secrets.yamlluks-passphrasePassphrase partagée du parcChiffré sops
secrets.yamlluks/<hôte>/passphrasePassphrase par hôteChiffré sops
/var/lib/luks-initrd/ (cible)Clé d’hôte SSH de l’initrdPersistant, 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).