ITSkillsCenter
Business Digital

Gérer les secrets NixOS avec agenix : tutoriel pas-à-pas

8 min de lecture

📍 Guide principal : NixOS pour développeurs et serveurs : reproductibilité totale en 2026
Ce tutoriel suppose un flake fonctionnel pour gérer un serveur NixOS (cf. nixos-rebuild remote).

Le problème des secrets dans une infra déclarative

Tout le pari de NixOS est de versionner la configuration entière du système dans git. C’est puissant pour la reproductibilité, mais ça pose une question évidente : où mettent-on les mots de passe de base de données, les tokens d’API, les clés privées TLS, les credentials SMTP ? Les commit en clair dans le dépôt est inacceptable. Les écrire à la main dans /etc sur chaque serveur défait l’idée même de configuration déclarative. Les sortir dans un coffre externe (Vault, AWS Secrets Manager) ajoute une dépendance lourde pour des projets de taille moyenne.

agenix propose une solution élégante. Les secrets sont chiffrés au repos avec les clés SSH publiques des hôtes qui doivent les lire. Ils sont commit dans le dépôt sous forme chiffrée. À l’activation d’une nouvelle génération NixOS, un script déchiffre chaque secret avec la clé privée SSH du serveur (qui n’est jamais sortie de la machine) et le pose dans /run/agenix/<nom>. Vos services lisent depuis ce chemin. Aucun secret en clair dans git, aucune dépendance externe, le rollback fonctionne.

Ce tutoriel monte agenix de zéro : génération des clés, premier secret, intégration au flake, déploiement, et résolution des erreurs courantes.

Prérequis

  • Un flake NixOS qui décrit au moins un serveur (cf. tutoriel nixos-rebuild remote).
  • Une clé SSH ED25519 sur votre poste de travail et sur le serveur cible (typiquement /etc/ssh/ssh_host_ed25519_key.pub côté serveur).
  • L’outil age ou son binaire seront fournis par le flake — pas besoin d’installer manuellement.

Étape 1 — Récupérer la clé publique du serveur

Chaque serveur a une clé SSH générée à l’installation, dans /etc/ssh/ssh_host_ed25519_key.pub. C’est cette clé publique qui sert à chiffrer les secrets pour ce serveur précis. Récupérez-la depuis votre poste :

ssh deploy@vps01.exemple.fr "cat /etc/ssh/ssh_host_ed25519_key.pub"

La sortie ressemble à ssh-ed25519 AAAAC3Nz... root@vps01. Copiez la ligne entière. Vous aurez besoin de la même chose pour chaque serveur qui doit pouvoir lire des secrets, et pour la clé personnelle de chaque opérateur qui doit pouvoir éditer les secrets.

Étape 2 — Ajouter agenix au flake

Modifiez votre flake.nix d’infra pour ajouter agenix comme input et exposer son module :

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
    agenix.url = "github:ryantm/agenix";
    agenix.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, nixpkgs, agenix }: {
    nixosConfigurations.vps01 = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ./hosts/vps01/configuration.nix
        agenix.nixosModules.default
      ];
    };
  };
}

Le module agenix.nixosModules.default expose les options age.secrets.<nom> dans votre configuration NixOS. C’est ce qui permettra de référencer les secrets dans vos services.

Étape 3 — Déclarer la liste des destinataires

Créez un fichier secrets/secrets.nix à la racine du dépôt qui liste qui peut chiffrer/déchiffrer chaque secret. C’est ce fichier qui pilote agenix.

let
  alice = "ssh-ed25519 AAAAC3Nz... alice@laptop";
  vps01 = "ssh-ed25519 AAAAC3Nz... root@vps01";
  vps02 = "ssh-ed25519 AAAAC3Nz... root@vps02";

  users = [ alice ];
  servers = [ vps01 vps02 ];
in {
  "db-password.age".publicKeys = users ++ [ vps01 ];
  "api-token.age".publicKeys = users ++ servers;
  "tls-cert.age".publicKeys = users ++ [ vps01 ];
}

Chaque entrée NOM.age liste les clés qui peuvent déchiffrer ce secret. users regroupe les opérateurs qui doivent pouvoir éditer (vous, votre coéquipier). servers regroupe les hôtes qui doivent pouvoir lire à l’activation. Si un secret est lu seulement par vps01, ajoutez seulement vps01 aux destinataires.

Étape 4 — Créer un premier secret

L’outil agenix en ligne de commande chiffre et déchiffre les secrets. Lancez-le via nix run :

cd secrets/
nix run github:ryantm/agenix -- -e db-password.age

Un éditeur s’ouvre ($EDITOR ou nano par défaut). Tapez votre mot de passe en clair, sauvegardez, fermez. agenix chiffre le contenu avec les clés publiques listées dans secrets.nix, et écrit db-password.age dans le dossier courant.

Vérifiez avec cat db-password.age : vous voyez du contenu binaire opaque, pas votre mot de passe. C’est ce fichier que vous commit dans git.

Étape 5 — Référencer le secret dans votre configuration

Dans hosts/vps01/configuration.nix, déclarez le secret côté NixOS :

{ config, pkgs, ... }:
{
  age.secrets.db-password.file = ../../secrets/db-password.age;

  services.postgresql = {
    enable = true;
    initialScript = pkgs.writeText "init.sql" ''
      CREATE USER app WITH PASSWORD 'TEMP';
    '';
  };

  systemd.services.app = {
    serviceConfig.LoadCredential = "db-pwd:${config.age.secrets.db-password.path}";
    script = ''
      DB_PASSWORD=$(cat $CREDENTIALS_DIRECTORY/db-pwd) ./run-app
    '';
  };
}

À l’activation, agenix déchiffre db-password.age avec la clé privée SSH du serveur et pose le contenu en clair dans /run/agenix/db-password. Le path est référencé via config.age.secrets.db-password.path. Le fichier est lisible uniquement par root par défaut ; pour un service tournant en utilisateur non-root, ajoutez age.secrets.db-password.owner = "app";.

Étape 6 — Déployer et vérifier

Commit vos changements (le .age chiffré et la config) puis déployez :

git add secrets/secrets.nix secrets/db-password.age \
        hosts/vps01/configuration.nix flake.nix flake.lock
git commit -m "Add db-password secret"

nixos-rebuild switch --flake .#vps01 \
  --target-host deploy@vps01.exemple.fr \
  --use-remote-sudo

Sur le serveur (en SSH), vérifiez que le secret est posé :

ssh deploy@vps01.exemple.fr
sudo ls -l /run/agenix/
sudo cat /run/agenix/db-password

Vous voyez le mot de passe en clair (parce que vous êtes root). Aucun utilisateur non-root ne peut le lire. Le secret est en mémoire (/run est un tmpfs) et ne touche pas le disque persistant.

Étape 7 — Modifier un secret

Pour changer la valeur d’un secret existant :

cd secrets/
nix run github:ryantm/agenix -- -e db-password.age

L’éditeur ouvre le contenu déchiffré, vous le modifiez, sauvegardez. agenix re-chiffre et écrit le nouveau .age. Commit, redéployez. À l’activation, le nouveau secret remplace l’ancien dans /run/agenix/, et systemd restart les services qui en dépendent (si vous avez bien déclaré la dépendance).

Étape 8 — Ajouter un opérateur ou un serveur aux destinataires

Quand un nouveau coéquipier arrive (Bob), ou que vous ajoutez un serveur (vps03), il faut re-chiffrer chaque secret avec les nouvelles clés. agenix automatise cette étape :

# Modifier secrets.nix pour ajouter Bob et vps03 aux publicKeys
nix run github:ryantm/agenix -- --rekey

--rekey parcourt tous les .age du dossier, les déchiffre avec votre clé privée, et les re-chiffre avec la nouvelle liste de destinataires. Commit le résultat ; les nouveaux destinataires peuvent désormais déchiffrer.

Erreurs fréquentes

Symptôme Cause Solution
error: agenix: identity could not be parsed Clé SSH privée pas trouvée ou pas ED25519. Vérifier ~/.ssh/id_ed25519 ou utiliser --identity pour pointer la bonne clé.
no identity matched any of the recipients Votre clé n’est pas dans les publicKeys du secret. Ajouter votre clé à secrets.nix, demander à un destinataire existant de faire --rekey.
Le secret n’apparaît pas dans /run/agenix/ Le serveur ne fait pas partie des publicKeys. Ajouter la clé du serveur, --rekey, redéployer.
Service redémarre en boucle après changement de secret Le service lit le secret au démarrage et plante à l’ancien path. Déclarer systemd.services.X.restartTriggers = [ config.age.secrets.X.file ];

Comparaison avec sops-nix

sops-nix est l’autre option populaire pour les secrets dans un flake NixOS. Il utilise sops (de Mozilla) en arrière-plan, avec support pour AWS KMS, GCP KMS, Azure Key Vault, age, et PGP. Le fichier de secrets est en YAML/JSON, plus lisible qu’un blob age opaque.

Quand choisir lequel ? agenix est plus simple, dépendance unique, idéal pour une petite infra où l’on commit dans git et on chiffre avec les clés SSH. sops-nix est plus flexible, intégré aux clouds, et permet une rotation automatique via les KMS — utile pour une équipe avec des contraintes de compliance. Les deux sont activement maintenus en 2026.

Bonnes pratiques

Ne jamais loguer le contenu d’un secret. Vérifiez vos services pour qu’ils ne crachent pas le DB password dans journalctl. Utiliser systemd LoadCredential plutôt que des variables d’environnement — c’est plus difficile à exfiltrer via /proc. Tourner les secrets régulièrement — une rotation tous les 90 jours, automatisable avec un cron job côté admin. Auditer les destinataires — quand un coéquipier quitte, retirer sa clé de secrets.nix et --rekey.

Suite logique

Avec agenix, vos secrets sont gérés comme du code. La suite naturelle est CI Nix : intégration continue avec flakes pour automatiser le déploiement post-PR sans exposer les secrets aux runners. Pour les images de serveur custom, Build d’un ISO NixOS et d’une AMI custom termine la série. Le guide principal NixOS est l’index général.

Références officielles

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité