Aller au contenu
Sécurité medium

NixOS : comprendre et modifier la configuration

18 min de lecture

NixOS décrit l’intégralité du système dans un fichier configuration.nix. Modifier ce fichier et lancer nixos-rebuild switch suffit pour ajouter un paquet, activer un service ou créer un utilisateur — sans toucher à un gestionnaire de paquets impératif. Ce guide vous montre comment explorer les options disponibles, modifier la configuration avec confiance, et factoriser le tout en modules lisibles. À la fin, votre VM dispose de fail2ban, d’un firewall, d’un second utilisateur et d’une configuration découpée en fichiers thématiques.

  • Explorer les options NixOS avec nixos-option et search.nixos.org
  • Ajouter et supprimer des paquets système (environment.systemPackages)
  • Activer et configurer des services : fail2ban, firewall, OpenSSH
  • Gérer les utilisateurs et les groupes déclarativement
  • Factoriser la configuration en modules (network.nix, users.nix)
  • Choisir entre nixos-rebuild switch, test et boot selon le contexte
  • Lire le diff de génération avant d’appliquer un changement

Ce lab correspond à la situation la plus courante sur NixOS : vous avez un système installé qui fonctionne, et vous voulez le faire évoluer.

  • Vous venez d’installer NixOS (Lab 1 ou Lab 2) et vous voulez ajouter fail2ban pour protéger SSH
  • Vous avez besoin d’un firewall qui n’autorise que le port 22
  • Vous devez créer un second utilisateur pour un collègue ou un service
  • Votre configuration.nix grossit et devient difficile à lire — il faut le découper en modules
  • Vous voulez comprendre la différence entre switch, test et boot avant de toucher à un serveur
  • Lab 1 ou Lab 2 terminé (VM NixOS fonctionnelle avec une flake)
  • Familiarité avec le langage Nix (attrsets, listes, with)
  • Notion de modules et imports

Le fichier configuration.nix est une fonction Nix qui reçoit un ensemble d’arguments et retourne un attribute set décrivant le système.

{ config, pkgs, modulesPath, ... }:
{
# 1. Imports : modules supplémentaires
imports = [ ... ];
# 2. Boot : chargeur de démarrage, modules noyau
boot.loader.systemd-boot.enable = true;
# 3. Réseau : hostname, firewall, interfaces
networking.hostName = "nixos-lab";
# 4. Services : SSH, fail2ban, etc.
services.openssh.enable = true;
# 5. Utilisateurs
users.users.lab = { ... };
# 6. Paquets système
environment.systemPackages = with pkgs; [ vim git ];
# 7. Options Nix
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# 8. Version d'état
system.stateVersion = "25.11";
}

Chaque ligne de ce fichier correspond à une option NixOS déclarée quelque part dans les modules de nixpkgs. Le système de modules fusionne automatiquement toutes les options de tous les fichiers importés.

NixOS propose plus de 15 000 options documentées. Deux outils pour les découvrir :

Fenêtre de terminal
# Voir la valeur actuelle, le type et la description d'une option
nixos-option services.openssh.enable

Résultat :

Value:
true
Default:
false
Type:
boolean
Description:
Whether to enable the OpenSSH secure shell daemon, which
allows secure remote logins.

Pour explorer les sous-options d’un service :

Fenêtre de terminal
nixos-option services.fail2ban
This attribute set contains:
banaction
banaction-allports
bantime
daemonConfig
daemonSettings
enable
extraPackages
extraSettings
ignoreIP
jails
maxretry
package
packageFirewall

Le site search.nixos.org/options propose une recherche full-text sur toutes les options NixOS. Tapez un mot-clé (ex : « fail2ban ») pour voir toutes les options associées, leur type, leur valeur par défaut et un lien vers le code source.

Les paquets système se déclarent dans environment.systemPackages :

environment.systemPackages = with pkgs; [
vim
git
htop
curl
tmux
];

Pour ajouter un paquet, ajoutez-le à la liste. Pour le supprimer, retirez-le. Après chaque modification :

Fenêtre de terminal
sudo nixos-rebuild switch --flake .#nixos-lab

Le paquet est installé ou supprimé immédiatement dans le profil système.

Fenêtre de terminal
nix search nixpkgs fail2ban

Cette commande interroge le cache nixpkgs pour trouver les paquets correspondants.

fail2ban surveille les logs d’authentification et bannit les IP qui échouent trop de fois. Sur NixOS, une seule section suffit :

services.fail2ban = {
enable = true;
maxretry = 5;
bantime = "10m";
ignoreIP = [ "127.0.0.1/8" "192.168.122.0/24" ];
};
  • maxretry = 5 : bannir après 5 échecs
  • bantime = "10m" : durée du bannissement
  • ignoreIP : ne jamais bannir ces réseaux (votre réseau local)

Le firewall NixOS est activé par défaut, mais bloquer explicitement tout sauf le nécessaire renforce la sécurité :

networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 ];
};

Seul le port 22 (SSH) est ouvert. Toute connexion entrante sur un autre port est rejetée.

Fenêtre de terminal
cd /etc/nixos
git add -A && git commit -m "add fail2ban and firewall"
sudo nixos-rebuild switch --flake .#nixos-lab

Vérifications :

Fenêtre de terminal
# fail2ban actif ?
systemctl is-active fail2ban
# active
# Règles firewall ?
sudo iptables -L nixos-fw -n
# Chain nixos-fw (1 references)
# target prot opt source destination
# nixos-fw-accept tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
# nixos-fw-log-refuse all -- 0.0.0.0/0 0.0.0.0/0
users.users.dev = {
isNormalUser = true;
description = "Développeur";
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAA... votre-cle-publique"
];
};
  • isNormalUser = true : crée un home directory et un shell standard
  • extraGroups = [ "wheel" ] : accès sudo
  • openssh.authorizedKeys.keys : connexion SSH par clé (pas de mot de passe)

Après nixos-rebuild switch, vérifiez :

Fenêtre de terminal
# L'utilisateur existe ?
id dev
# uid=1001(dev) gid=100(users) groupes=100(users),1(wheel)
# Connexion SSH depuis l'hôte ?
ssh dev@192.168.122.104 whoami
# dev

Retirez simplement le bloc users.users.dev de la configuration et appliquez. NixOS désactive le compte, mais ne supprime pas le home directory par sécurité.

nixos-rebuild propose trois modes d’application :

CommandeEffet immédiatBoot suivantGénération créée
switchOui — active immédiatementOuiOui
testOui — active immédiatementNon — revient à l’ancienneNon
bootNon — rien ne changeOui — active au rebootOui
  • test : vous voulez vérifier qu’un changement fonctionne avant de le rendre permanent. Si le système plante, un reboot revient à l’état précédent.
  • switch : le cas standard — appliquer immédiatement et rendre permanent.
  • boot : changement de noyau ou de bootloader — vous voulez que ça prenne effet au prochain reboot sans perturber le système en cours.
Fenêtre de terminal
# Tester d'abord (recommandé pour les changements risqués)
sudo nixos-rebuild test --flake .#nixos-lab
# Si tout va bien, appliquer
sudo nixos-rebuild switch --flake .#nixos-lab

Avant d’appliquer un changement, vous pouvez voir exactement ce qui va changer en termes de paquets :

Fenêtre de terminal
nix profile diff-closures --profile /nix/var/nix/profiles/system

Résultat (extrait) :

Version 2 -> 3:
fail2ban: ∅ → 1.1.0, +5144.9 KiB
python3.13-pyinotify: ∅ → 0.9.6, +296.0 KiB
python3.13-systemd-python: ∅ → 235, +403.1 KiB
Version 3 -> 4:
NetworkManager: ∅ → ..., +X KiB
dnsmasq: ∅ → 2.91, +623.2 KiB

Chaque transition montre les paquets ajoutés (∅ → version), supprimés (version → ∅) et mis à jour (ancienne → nouvelle). C’est l’équivalent d’un git diff pour votre système.

Fenêtre de terminal
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
1 2026-04-14 10:47:12
2 2026-04-14 11:09:05
3 2026-04-14 19:19:57
4 2026-04-14 19:21:14 (current)

Chaque nixos-rebuild switch crée une nouvelle génération. Vous pouvez revenir à n’importe laquelle depuis le boot loader — c’est le sujet du Lab 9.

Quand configuration.nix grossit, découpez-le en fichiers thématiques. NixOS fusionne automatiquement tous les modules importés.

Extrayez tout ce qui concerne le réseau et la sécurité réseau :

/etc/nixos/network.nix
{ config, ... }:
{
networking.hostName = "nixos-lab";
networking.networkmanager.enable = true;
networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 ];
};
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "prohibit-password";
PasswordAuthentication = false;
};
};
services.fail2ban = {
enable = true;
maxretry = 5;
bantime = "10m";
ignoreIP = [ "127.0.0.1/8" "192.168.122.0/24" ];
};
}

Extrayez la gestion des utilisateurs :

/etc/nixos/users.nix
{ config, ... }:
{
users.users.lab = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAA... votre-cle-publique"
];
};
users.users.dev = {
isNormalUser = true;
description = "Développeur";
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAA... votre-cle-publique"
];
};
security.sudo.wheelNeedsPassword = false;
}

Le fichier principal ne contient plus que le socle :

/etc/nixos/configuration.nix
{ config, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
./network.nix
./users.nix
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.initrd.availableKernelModules = [
"virtio_pci" "virtio_blk" "virtio_scsi" "ahci" "sd_mod"
];
boot.kernelModules = [ "virtio_net" ];
time.timeZone = "Europe/Paris";
i18n.defaultLocale = "fr_FR.UTF-8";
console.keyMap = "fr";
environment.systemPackages = with pkgs; [
vim git htop curl tmux
];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
system.stateVersion = "25.11";
}

Appliquez et vérifiez que tout fonctionne identiquement :

Fenêtre de terminal
cd /etc/nixos
git add -A && git commit -m "refactor: split into network.nix and users.nix"
sudo nixos-rebuild switch --flake .#nixos-lab

NixOS fusionne les trois fichiers au moment de l’évaluation. Le résultat est strictement identique à un fichier monolithique — les services et utilisateurs sont préservés.

Si vous avez suivi le Lab 2 (installation sans disko), vous avez un fichier hardware-configuration.nix généré par nixos-generate-config. Il contient :

  • Les modules noyau nécessaires au matériel détecté (virtio, ahci, etc.)
  • Les points de montage avec les UUID des partitions
  • Le profil de virtualisation (qemu-guest.nix pour les VM KVM)
# Exemple généré
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = [
"ahci" "xhci_pci" "virtio_pci" "virtio_blk"
];
fileSystems."/" = {
device = "/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/XXXX-XXXX";
fsType = "vfat";
};
}
  1. fail2ban est actif

    Fenêtre de terminal
    systemctl is-active fail2ban
    # active
  2. Le firewall n’autorise que le port 22

    Fenêtre de terminal
    sudo iptables -L nixos-fw -n
    # nixos-fw-accept tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
    # nixos-fw-log-refuse all -- 0.0.0.0/0 0.0.0.0/0
  3. Le second utilisateur fonctionne

    Fenêtre de terminal
    id dev
    # uid=1001(dev) gid=100(users) groupes=100(users),1(wheel)
    ssh dev@192.168.122.104 whoami
    # dev
  4. La factorisation en modules est transparente

    Fenêtre de terminal
    ls /etc/nixos/*.nix
    # configuration.nix disko-config.nix flake.nix network.nix users.nix
    sudo nixos-rebuild switch --flake .#nixos-lab
    # Done. The new configuration is /nix/store/...
  5. Les générations sont visibles

    Fenêtre de terminal
    sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
    # 1 2026-04-14 10:47:12
    # 2 2026-04-14 11:09:05
    # 3 2026-04-14 19:19:57
    # 4 2026-04-14 19:21:14 (current)
  6. Le diff de génération montre les changements

    Fenêtre de terminal
    nix profile diff-closures --profile /nix/var/nix/profiles/system
    # Version 2 -> 3:
    # fail2ban: ∅ → 1.1.0, +5144.9 KiB
SymptômeCause probableSolution
nixos-rebuild : « error: attribute ‘xxx’ missing »Option mal orthographiéeVérifier avec nixos-option ou search.nixos.org
Un service n’est pas actif après switchL’option enable = true est absenteAjouter services.<name>.enable = true
Firewall bloque un service légitimePort non déclaréAjouter le port à networking.firewall.allowedTCPPorts
hardware-configuration.nix modifié par erreurModification manuellesudo nixos-generate-config pour régénérer
Conflit entre deux modules (même option)Deux fichiers définissent la même option avec des valeurs incompatiblesUtiliser lib.mkForce ou lib.mkDefault pour la priorité, ou regrouper l’option dans un seul module
nixos-rebuild test fonctionne mais switch échoueProblème d’écriture du bootloaderVérifier que /boot est monté et que canTouchEfiVariables = true
Nouveau paquet absent du PATHnix-rebuild switch pas exécutéRelancer sudo nixos-rebuild switch --flake .#hostname
  1. configuration.nix est une fonction Nix qui décrit l’état complet du système — chaque ligne correspond à une option NixOS documentée
  2. nixos-option et search.nixos.org sont les deux outils de référence pour découvrir et comprendre les options disponibles
  3. Ajouter un service = déclarer services.<name>.enable = true + les options souhaitées, puis nixos-rebuild switch
  4. nixos-rebuild test applique sans rendre permanent — idéal pour valider un changement risqué avant switch
  5. nix profile diff-closures montre exactement ce qui change entre deux générations — utilisez-le avant chaque switch important
  6. Factorisez en modules dès que la configuration dépasse 100 lignes — NixOS fusionne automatiquement tous les imports
  7. Ne créez jamais rien de façon impérative (useradd, apt install) — tout changement non déclaré sera perdu au prochain switch

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn