Aller au contenu

Modules système

Module principal de DNF.

Configure le chargeur systemd-boot, le noyau LTS (ou le dernier noyau stable via enableLatestKernel), la JetBrains Mono Nerd Font (avec kmscon pour le TTY), l’optimisation nocturne du magasin Nix et la collecte hebdomadaire des ordures (rétention de 30 jours, ou keep-last-N via gcKeepGenerations sur les hôtes à espace disque limité), le pare-feu, la politique de veille (les serveurs peuvent la désactiver complètement via disableSuspend), les règles polkit autorisant le groupe wheel à arrêter/redémarrer, et un groupe/utilisateur common-files partagé pour les dossiers médias inter-services.

  • enable bool Système principal du framework Darkone (activé par défaut)
  • enableSystemdBoot bool Activer le chargeur de démarrage par défaut
  • enableLatestKernel bool Utiliser le dernier noyau stable (linuxPackages_latest) au lieu du noyau LTS
  • enableFstrim bool Optimisation SSD avec fstrim
  • enableFirewall bool Activer le pare-feu (vrai par défaut)
  • enableSops bool Activer le module sops dnf (vrai par défaut)
  • enableFlatpak bool Activer la configuration flatpak DNF (uniquement pour les environnements graphiques)
  • enableKmscon bool Activer la nerd font pour le TTY
  • gcKeepGenerations int Lorsque > 0, tronquer le profil système aux N dernières générations avant chaque collecte des ordures, et collecter quotidiennement sans rétention basée sur l’âge. Pour les hôtes avec une partition racine serrée (passerelles).
  • enableBoost bool Activer l’overclocking, corectl
  • enableAutoSuspend bool Activer la veille automatique (pour les portables, ignoré si disableSuspend est vrai)
  • disableSuspend bool Désactivation complète de la veille (pour les serveurs)
  • enableCommonFilesUser bool Activer l’utilisateur common-files utilisé par plusieurs services
darkone.system.core = {
enable = true;
enableSystemdBoot = true;
enableLatestKernel = false;
enableFstrim = true;
enableFirewall = true;
enableSops = true;
enableFlatpak = true;
enableKmscon = true;
gcKeepGenerations = 5;
enableBoost = false;
enableAutoSuspend = false;
disableSuspend = false;
enableCommonFilesUser = false;
};

Documentation (man) pour les développeurs et les administrateurs.

  • enable bool Activer la documentation technique utile (man, nixos)
darkone.system.documentation.enable = false;

Améliorations de la configuration matérielle.

  • enable bool Activer les optimisations matérielles
  • enableIntel bool Activer les mises à jour du microcode Intel
  • enableAmd bool Activer les mises à jour du microcode AMD
darkone.system.hardware = {
enable = false;
enableIntel = false;
enableAmd = false;
};

Configuration de la localisation et de la langue.

  • enable bool Activer i18n avec la configuration de la zone de réseau par défaut
  • locale strMatching localeRegex Locale réseau, doit correspondre à la forme xx_YY.UTF-8.
  • timeZone str Fuseau horaire réseau
darkone.system.i18n = {
enable = false;
locale = "fr_FR.UTF-8";
timeZone = "Europe/Paris";
};

Politique de passphrase LUKS & déverrouillage distant : passphrases partagées et par hôte, SSH initrd.

Complète modules/system/yubikey.nix (keyslots FIDO2) avec le volet passphrase de la politique LUKS de la flotte. Chaque volume chiffré porte exactement deux passphrases gérées, plus un keyslot par YubiKey enrôlée :

KeyslotSecretAudience
partagéesops luks-passphrasel’admin de la flotte. Autorise aussi les opérations de keyslot (luksAddKey / luksKillSlot) pour les unités ci-dessous, et c’est la clé avec laquelle disko formate le disque.
par-hôtesops luks/<host>/passphrasel’utilisateur de la machine en question, sans remettre la flotte en jeu.
FIDO2registry usr/secrets/yubikeys.jsonun slot par clé, sur chaque hôte chiffré.

Deux passphrases gérées et non une seule, car elles servent des personnes différentes — et parce qu’une rotation de l’une reste autorisée par l’autre : l’unité de synchronisation n’est jamais privée d’autoriseur (elle ajoute le nouveau slot avant de tuer l’ancien).

Il n’existe pas de « passphrase d’installation » distincte : just install formate le volume via nixos-anywhere --disk-encryption-keys avec la passphrase partagée, donc le keyslot de formatage est le keyslot partagé.

just luks <host> provisionne un hôte (idempotent, aussi appelé par just configure) ; sa phase pre s’exécute hors ligne et est appelée par just install avant la compilation. Il enregistre l’hôte dans le manifeste public usr/secrets/luks.json (commité), stocke la passphrase par-hôte et la clé d’hôte SSH de l’initrd dans sops, et garantit l’existence de la luks-passphrase partagée. just luks <host> show affiche le tableau des keyslots et audite le déverrouillage distant. Le module maintient ensuite tout converge à chaque apply :

  • keyslots : un service oneshot synchronise les passphrases partagées et par-hôte dans chaque en-tête LUKS2 déclaré par disko. Une valeur sops modifiée fait tourner le keyslot correspondant (ancien slot tué, nouveau ajouté). Les opérations de keyslot sont autorisées par la passphrase gérée qui déverrouille encore le volume : l’une d’elles doit donc rester valide. Les slots hors de sa comptabilité (FIDO2, enrôlements manuels) ne sont jamais touchés.
  • déverrouillage distant : sshd de l’initrd sur un port dédié (2222), propre clé d’hôte persistante (/var/lib/luks-initrd/), connexion root avec la clé de déploiement nix (usr/secrets/nix.pub). just unlock <host> répond à l’invite de passphrase sans humain (via l’aide dnf-unlock embarquée dans l’initrd) ; just enter <host> est le chemin interactif. Les deux basculent sur l’IP WAN enregistrée dans le manifeste quand la route VPN est morte avec l’hôte. Les hôtes classiques utilisent DHCP sur les interfaces filaires (un portable en Wi-Fi n’a pas de réseau initrd et bascule sur le déverrouillage console) ; les passerelles de zone répliquent leur layout de production — IP LAN statique sur le bridge lan0, DHCP côté WAN — puisqu’elles sont elles-mêmes le serveur DHCP que leur initrd attendrait sinon.
  • enable bool Politique de passphrase LUKS de la flotte (inerte jusqu’à ce que just luks &lt;host&gt; provisionne l’hôte)
  • sshPort port Port sshd de l’initrd ; distinct de 22 pour que la clé d’hôte de l’initrd n’entre jamais en conflit avec celle du système
  • volumes listOf str Volumes LUKS déclarés par le layout disko de l’hôte.
darkone.system.luks = {
enable = true;
sshPort = 2222;
volumes = [ ];
};

Durcissement système ANSSI BP-028 v2.0 (GNU/Linux). (wip)

Module recommandé, activé dans certains profils d’hôtes ou manuellement selon les besoins. Applique progressivement les recommandations ANSSI selon le niveau choisi et la catégorie de machine. Chaque profil d’hôte définit son niveau et sa catégorie :

darkone.system.security = {
level = "intermediary"; # minimal | intermediary | reinforced | high
category = "server"; # base | client | server
};

Les règles incompatibles avec l’environnement sont exclues par tag :

darkone.system.security.excludes = [ "needs-jit" "needs-hibernation" ];

Une règle spécifique peut être contournée avec une justification obligatoire :

darkone.system.security.exceptions = {
R9.rationale = "Docker rootless required during development.";
};
  • enable bool Activer le module de durcissement ANSSI BP-028 v2.0.
  • level enum [ "minimal" "intermediary" "reinforced" "high" ] Niveau de durcissement ANSSI visé.
  • category enum [ "base" "client" "server" ] Catégorie de machine qui sélectionne les sous-ensembles de règles.
  • excludes listOf str Tags qui désactivent des groupes entiers de règles.
  • exceptions attrs Exceptions par règle avec justification obligatoire.
  • adminMailbox str Adresse e-mail de l’administrateur (sudo R39, alias MTA R75).
  • useHardenedKernel bool Utiliser linuxPackages_hardened (R60, C1) au lieu du noyau par défaut.
  • allowedActiveUsers listOf str Comptes humains autorisés à s’authentifier (R30). Par défaut, chaque utilisateur déclaré dans config.yaml (host.users) plus le compte de déploiement du framework nix. Les comptes désactivés (sans justificatif de mot de passe) et les comptes de service (qui ne sont pas des utilisateurs normaux) n’ont pas besoin d’être listés.
darkone.system.security = {
enable = false;
level = "minimal";
category = "base";
excludes = [ ];
exceptions = { };
adminMailbox = "admin@exemple.fr";
useHardenedKernel = false;
allowedActiveUsers = [ ];
};

Enregistrement et configuration des services DNF.

  • enable bool Activer le gestionnaire de services DNF pour enregistrer et exposer les services
  • service attrs Configuration globale des services <nom>
    • enable bool Activer le proxy de service
    • defaultParams submodule Ces options sont calculées par dnfLib.srv.extractServiceParams
      • domain str Nom de domaine pour le service
      • title str Nom affiché sur la page d’accueil
      • description str Description du service pour la page d’accueil
      • icon str Nom de l’icône pour la page d’accueil 🡕
      • global bool Service global accessible sur Internet
      • noRobots bool Empêcher les robots de scanner si global est vrai
      • fqdn str FQDN calculé du service avant le proxy inverse
      • href str URL calculée du service avant le proxy inverse
      • ip str IP calculée pour contacter le service
    • displayOnHomepage bool Afficher un lien sur la page d’accueil
    • reverseProxy bool Accessible via le proxy inverse de la passerelle de zone (DNS pointe vers l’IP LAN de la passerelle)
    • uniquePerZone bool Au plus une instance autorisée par zone (validation du générateur)
    • externalAccess bool Service de zone www accessible depuis le LAN via une IP hôte fixe (p. ex. headscale, turn)
    • persist.dirs listOf str Répertoires persistants du service
    • persist.files listOf str Fichiers persistants du service
    • persist.dbDirs listOf str Répertoires persistants du service avec base(s) de données
    • persist.dbFiles listOf str Fichier(s) de base de données du service
    • persist.varDirs listOf str Fichiers secondaires variables (log, cache, etc.)
    • persist.mediaDirs listOf str Répertoires média du service (images, vidéos, gros fichiers)
    • proxy.enable bool Créer une configuration virtualHost (false pour les services qui gèrent la leur)
    • proxy.isProtected bool Service protégé par Oauth2
    • proxy.allowedGroups listOf str Groupes Kanidm autorisés sur ce service protégé (vide = tout utilisateur authentifié)
    • proxy.isInternal bool Lier le service sur l’interface interne uniquement (pas accessible depuis Internet)
    • proxy.hasReverseProxy bool Ceci est un proxy inverse (ou une autre configuration virtualHost via extraConfig)
    • proxy.defaultService bool Est le service par défaut
    • proxy.servicePort nullOr port Port interne du service
    • proxy.preExtraConfig lines Configuration virtualHost caddy supplémentaire (préfixe)
    • proxy.extraConfig lines Configuration virtualHost caddy supplémentaire
    • proxy.extraGlobalConfig lines Configuration caddy supplémentaire
    • proxy.scheme str Schéma interne du service (http / https)
darkone.system.services = {
enable = false;
service.enable = false;
service.defaultParams.domain = "";
service.defaultParams.title = "";
service.defaultParams.description = "";
service.defaultParams.icon = "";
service.defaultParams.global = false;
service.defaultParams.noRobots = true;
service.defaultParams.fqdn = "";
service.defaultParams.href = "";
service.defaultParams.ip = "";
service.displayOnHomepage = true;
service.reverseProxy = true;
service.uniquePerZone = false;
service.externalAccess = false;
service.persist.dirs = [ ];
service.persist.files = [ ];
service.persist.dbDirs = [ ];
service.persist.dbFiles = [ ];
service.persist.varDirs = [ ];
service.persist.mediaDirs = [ ];
service.proxy.enable = true;
service.proxy.isProtected = false;
service.proxy.allowedGroups = [ ];
service.proxy.isInternal = false;
service.proxy.hasReverseProxy = true;
service.proxy.defaultService = false;
service.proxy.servicePort = null;
service.proxy.preExtraConfig = "";
service.proxy.extraConfig = "";
service.proxy.extraGlobalConfig = "";
service.proxy.scheme = "https";
};

Gestion DNF de sops, mots de passe et secrets.

Branche sops-nix sur usr/secrets/secrets.yaml et le déverrouille avec la clé SSH de l’hôte (ssh_host_ed25519_key) ainsi que la clé age d’infrastructure dédiée (/etc/sops/age/infra.key). Déclare un secret user/<login>/password-hash par utilisateur d’hôte, avec neededForUsers = true afin que le hash soit disponible avant la création des comptes utilisateurs.

Rien d’autre n’est matérialisé ici : un secret appartient aux hôtes qui le consomment, déclaré par le module qui le lit. default-password-hash reste dans le fichier chiffré, illisible par aucun hôte : il enregistre le mot de passe par défaut de la flotte pour just passwd <login>.

  • enable bool Active la configuration automatisée de sops pour DNF
darkone.system.sops.enable = false;

Service de gestion des répertoires partagés.

  • enable bool Activer les répertoires partagés, créer le répertoire racine (défaut /srv)
  • enableNfs bool Activer les chemins du service NFS (nfs/common, nfs/homes)
  • enableMedias bool Activer les chemins des services média (medias/[videos|music|incomming/…])
  • enableStk bool Activer le chemin de partage des pistes SuperTuxKart (nfs/stk-tracks)
  • root str Répertoire racine des données persistantes (/srv)
  • nfs str Répertoire racine NFS (/srv/nfs)
  • homes str Répertoire des domiciles partagés (/srv/nfs/homes)
  • common str Répertoire commun partagé (/srv/nfs/common lié à ~/Public)
  • stkTracks str Répertoire des pistes SuperTuxKart partagées (/srv/nfs/stk-tracks)
  • medias str Répertoire racine des médias (/srv/medias)
  • music str Répertoire des fichiers musicaux partagés (/srv/medias/music)
  • videos str Répertoire des fichiers vidéo partagés (/srv/medias/videos)
  • incoming str Répertoire des fichiers entrants partagés (/srv/medias/incoming accès en écriture)
  • incomingMusic str Répertoire des fichiers entrants partagés (/srv/medias/incoming/music accès en écriture)
  • incomingVideos str Répertoire des fichiers entrants partagés (/srv/medias/incoming/videos accès en écriture)
darkone.system.srv-dirs = {
enable = cfg.enableNfs || cfg.enableMedias || cfg.enableStk;
enableNfs = false;
enableMedias = false;
enableStk = false;
root = "/srv";
nfs = null;
homes = null;
common = null;
stkTracks = null;
medias = null;
music = null;
videos = null;
incoming = null;
incomingMusic = null;
incomingVideos = null;
};

Mode test autonome pour le NixOS Test Driver.

Quand activé, neutralise les parties irréductiblement externes/exécution afin qu’un nœud puisse être testé dans une VM : headscale/tailscale deviennent des no-op et un certificat TLS fixe peut simuler ACME. Permet également à la configuration propre à workDir (nix.pub, harmonia.pub) d’être ignorée par core/nix-cache. sops reste RÉEL (haute fidélité).

  • standalone bool Mode test autonome — ignore la configuration propre à workDir (nix.pub, harmonia.pub) et neutralise les services externes
  • tlsCert nullOr path Certificat auto-signé (PEM) fourni par le harnais de test pour simuler ACME. Jamais un chemin tests/ intégré dans le framework.
  • tlsKey nullOr path Clé privée (PEM) associée à tlsCert.
darkone.system.testing = {
standalone = false;
tlsCert = null;
tlsKey = null;
};

Authentification forte YubiKey : PAM U2F + FIDO2 LUKS déclaratif sur toute la flotte.

Un inscription physique par (utilisateur, clé) sur l’administrateur — just yubikey <user> [key] [action] — alimente :

  • un registre public usr/secrets/yubikeys.json dans l’espace de travail consommateur : identifiant pamu2fcfg, identifiant et sel du FIDO2 hmac-secret (inutilisable sans la clé physique, donc commitable) ;
  • un secret sops yubikey/<user>/<key>/luks-secret (la phrase secrète LUKS dérivée du FIDO2) ainsi que le luks-passphrase partagé (la phrase secrète saisie lors de l’installation disko, nécessaire pour autoriser de nouveaux keyslots).

Le module propage ensuite tout de façon déclarative (just apply), sans jamais brancher la clé sur les hôtes cible :

  • login / sudo / greeter : pam_u2f en alternative au mot de passe (sufficient) : toucher la clé connecte, le mot de passe sops reste le repli automatique. Un identifiant est valide sur toute la flotte grâce à l’origine fixe (pam://<network.domain>).
  • hôtes chiffrés : un service oneshot inscrit automatiquement chaque clé déclarée dans chaque en-tête LUKS2 déclaré par disko (keyslot + systemd-fido2 token, le format exact écrit par systemd-cryptenroll) et purge les clés révoquées. La clé physique n’est nécessaire qu’au démarrage pour déverrouiller le disque.
  • enable bool Authentification YubiKey (désactivé par défaut ; activé quand usr/secrets/yubikeys.json existe)
  • origin str Origine/appid pam_u2f fixe : une inscription est valide sur toute la flotte
  • luks.enable bool Déverrouillage FIDO2 des volumes LUKS de l’hôte (inerte sans disko LUKS + clés inscrites)
darkone.system.yubikey = {
enable = hasRegistry;
origin = "pam://${network.domain}";
luks.enable = true;
};