Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Écrire une première configuration NixOS

Par mis à jour le

Améliorer cette page

Un fichier configuration.nix est une expression Nix qui déclare l'état complet d'un système NixOS. Vous ne lancez pas de commandes pour installer des paquets ou activer des services, vous décrivez ce que vous voulez, et nixos-rebuild switch calcule exactement ce qu'il faut faire. Maîtriser configuration.nix, c'est maîtriser la couche qui transforme le langage Nix (attrsets, fonctions, options) en système vivant. Ce guide montre comment franchir le saut entre « je connais les attrsets » et « j'ai une configuration système qui fonctionne ». Les comportements du système de modules décrits ici ont été vérifiés par évaluation avec Nix 2.35.2 et le nixpkgs du 29 septembre 2026 ; ce qui exige une machine NixOS réelle (nixos-rebuild, nixos-option) suit le manuel NixOS 26.05.

  • Lire la structure générale d'un fichier Nix : expression, arguments { config, pkgs, ... }:, bloc de sortie
  • Comprendre l'anatomie d'un configuration.nix minimal section par section
  • Distinguer un paquet (pkgs.xxx) d'une option NixOS (services.xxx.enable)
  • Trouver la bonne option dans la documentation NixOS avec search.nixos.org et nixos-option
  • Écrire une configuration concrète : paquets, SSH sécurisé, utilisateur admin
  • Appliquer les changements avec nixos-rebuild switch sans redémarrer la machine
  • Modulariser en fichiers séparés avec imports

Dès que vous travaillez sur un système NixOS, en VM de test, en serveur de production ou en homelab, configuration.nix est le fichier central. Savoir le lire et le modifier devient indispensable pour :

  • personnaliser un serveur NixOS installé depuis une image ou un template cloud,
  • reproduire un environnement identique sur plusieurs machines depuis un dépôt Git,
  • activer un service (SSH, Docker, Nginx) sans chercher la bonne commande d'installation,
  • diagnostiquer pourquoi un service ne démarre pas après un rebuild,
  • préparer la migration vers les flakes en comprenant d'abord la configuration de base.

Ce guide s'appuie sur les bases du langage Nix (attrsets, fonctions, let, with). Si ces notions ne sont pas encore familières, commencez par ce guide.

Tout fichier .nix est une expression, une valeur calculée, pas un script. Un configuration.nix est une fonction qui reçoit des arguments et retourne un attrset d'options :

{ config, pkgs, ... }:
{
# vos options ici
}

Les trois parties essentielles :

PartieRôle
{ config, pkgs, ... }:Arguments que NixOS injecte à l'évaluation. config expose les valeurs de toute la config ; pkgs donne accès à nixpkgs. ... accepte d'autres arguments sans les nommer.
{ ... }Le corps de la fonction : un attrset dont chaque attribut est une option NixOS (networking.hostName, services.openssh.enable, etc.).
;Chaque option dans l'attrset se termine par un point-virgule, c'est la syntaxe Nix, pas du YAML.

Voici le squelette complet d'une configuration de base, commenté section par section :

{ config, pkgs, ... }:
{
# ── 1. Imports ──────────────────────────────────────────────────────────────
imports = [
./hardware-configuration.nix # généré automatiquement lors de l'installation
];
# ── 2. Bootloader ───────────────────────────────────────────────────────────
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# ── 3. Réseau ───────────────────────────────────────────────────────────────
networking.hostName = "monserveur";
networking.networkmanager.enable = true;
# ── 4. Locale et fuseau horaire ─────────────────────────────────────────────
time.timeZone = "Europe/Paris";
i18n.defaultLocale = "fr_FR.UTF-8";
# ── 5. Paquets système ──────────────────────────────────────────────────────
environment.systemPackages = with pkgs; [
git
vim
curl
wget
];
# ── 6. Services ─────────────────────────────────────────────────────────────
services.openssh.enable = true;
# ── 7. Utilisateurs ─────────────────────────────────────────────────────────
users.users.admin = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
# ── 8. Version d'état ───────────────────────────────────────────────────────
system.stateVersion = "26.05"; # ← ne jamais modifier après l'installation
}
SectionCe qu'elle contrôleRemarque importante
importsFichiers .nix inclus dans l'évaluationhardware-configuration.nix est généré par nixos-generate-config
boot.loaderGRUB ou systemd-boot, BIOS ou UEFIDépend du mode de démarrage de votre machine
networking.*Nom d'hôte, interfaces, DNS, firewallnetworkmanager pour les postes de travail, firewall pour les serveurs
time.timeZoneFuseau horaire systèmeFormat IANA : Europe/Paris, UTC, America/New_York
environment.systemPackagesPaquets disponibles pour tous les utilisateurswith pkgs; importe le scope nixpkgs dans la liste
services.*Activation et configuration des servicesUn module NixOS par service
users.users.*Déclaration des utilisateurs et groupesChaque utilisateur est un attrset de sa propre configuration
system.stateVersionVersion NixOS au moment de l'installation initialeNe jamais modifier, gère la compatibilité des données persistantes

Dans ce tableau, la colonne Remarque importante est celle qui évite les mauvaises surprises. Deux lignes méritent une lecture attentive : imports, parce que hardware-configuration.nix décrit les disques et le matériel détectés à l'installation et qu'un fichier absent bloque le rebuild ; et system.stateVersion, qui fige le comportement des services stateful (format des bases PostgreSQL, emplacement des données) et ne suit donc pas la version de NixOS installée.

C'est la source de confusion la plus fréquente pour les nouveaux utilisateurs NixOS : un paquet rend un binaire disponible, une option décrit un comportement du système.

Paquet (pkgs.xxx)Option service (services.xxx.enable)
Ce que c'estUn logiciel à rendre disponibleUne déclaration de comportement système
Où on le placeDans environment.systemPackagesDirectement dans le corps de la config
Ce qu'il faitRend le binaire accessible dans PATHInstalle le paquet et configure et démarre le service
Exemplepkgs.nginx (juste le binaire)services.nginx.enable = true; (le tout)

Règle pratique : si un service a un module NixOS (services.xxx), utilisez-le, il gère les paquets, la configuration et l'unité systemd. N'ajoutez pas nginx dans environment.systemPackages si vous utilisez services.nginx.enable = true;.

# CORRECT : le module NixOS gère tout
services.nginx.enable = true;
# INCORRECT : Redondant et source de conflits
environment.systemPackages = with pkgs; [ nginx ];
services.nginx.enable = true;

Le nom exact d'une option ne se devine pas : services.openssh.settings.PasswordAuthentication ne ressemble en rien au PasswordAuthentication no d'un sshd_config. Trois outils répondent à la question, du plus rapide au plus précis. Le moteur web sert à explorer un domaine que vous ne connaissez pas ; nixos-option répond sur votre machine, avec la valeur réellement appliquée ; nix repl sert quand vous voulez inspecter la structure d'un module avant d'écrire quoi que ce soit.

1. search.nixos.org, le moteur officiel, le plus rapide :

https://search.nixos.org/options?query=openssh

2. nixos-option, interroge les options disponibles sur le système actif :

Fenêtre de terminal
# Lister les sous-options d'un service
nixos-option services.openssh
# Obtenir valeur actuelle + description d'une option
nixos-option services.openssh.enable
# Value: true
# Default: false
# Description: Whether to enable the OpenSSH secure shell daemon, which allows secure remote logins.
# Declared by: <nixpkgs/nixos/modules/services/networking/ssh/sshd.nix>

3. nix repl avec nixpkgs chargé :

Fenêtre de terminal
nix repl --file '<nixpkgs/nixos>'
# nix-repl> :t options.services.openssh
# nix-repl> options.services.openssh.enable

Configurer un serveur NixOS avec les quatre éléments ci-dessous, chacun porté par une option précise que la configuration complète fait apparaître :

  • git, vim, curl, htop disponibles en ligne de commande
  • SSH activé avec authentification par mot de passe désactivée
  • Un utilisateur admin dans le groupe wheel (accès sudo)
  • Fuseau horaire Europe/Paris

Trois blocs de ce fichier portent les décisions réelles. Le bloc services.openssh.settings coupe l'authentification par mot de passe et le login root : si vous appliquez cette configuration sans avoir déposé votre clé publique au préalable, vous perdez l'accès distant à la machine. Le bloc users.users.admin contient la clé publique attendue, à remplacer par la vôtre. Enfin, security.sudo.wheelNeedsPassword = false; accorde un sudo sans mot de passe au groupe wheel : pratique en lab, à retirer sur une machine exposée où la compromission d'une session SSH donnerait directement le root.

{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "serveur-prod";
networking.networkmanager.enable = true;
time.timeZone = "Europe/Paris";
i18n.defaultLocale = "fr_FR.UTF-8";
environment.systemPackages = with pkgs; [
git
vim
curl
htop
];
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
PermitRootLogin = "no";
};
};
users.users.admin = {
isNormalUser = true;
description = "Administrateur système";
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... votre_cle_publique"
];
};
security.sudo.wheelNeedsPassword = false;
system.stateVersion = "26.05";
}

L'ordre des quatre étapes n'est pas décoratif. dry-build évalue l'expression Nix et affiche ce qui serait construit ou téléchargé, sans rien construire ni toucher au système : une accolade oubliée ou un paquet inexistant échoue ici, pas après avoir désactivé SSH. L'étape de vérification est la seule qui prouve que la configuration a produit l'effet attendu : un nixos-rebuild switch qui se termine sans erreur signifie que le système a été activé, pas que le service tourne.

  1. Éditer le fichier (en root ou via sudo)

    Fenêtre de terminal
    sudo vim /etc/nixos/configuration.nix
  2. Valider la configuration sans l'appliquer

    Fenêtre de terminal
    sudo nixos-rebuild dry-build
    # Évaluer et lister ce qui serait construit : sortie d'erreur si syntaxe ou option incorrecte
  3. Appliquer les changements

    Fenêtre de terminal
    sudo nixos-rebuild switch
    # Build + activation immédiate + entrée par défaut dans le bootloader
  4. Vérifier le résultat

    Fenêtre de terminal
    # Paquets disponibles ?
    which git vim curl htop
    # SSH démarré ?
    systemctl status sshd
    # Utilisateur créé ?
    id admin

Les cinq erreurs qui suivent représentent l'essentiel des blocages rencontrés lors des premiers nixos-rebuild. Lisez d'abord la colonne Symptôme : c'est elle qui correspond à ce que vous avez sous les yeux. Les quatre premières lignes échouent à l'évaluation, avec un message explicite, et ne cassent donc rien. La dernière est plus sournoise : le rebuild réussit, mais le résultat n'est pas celui attendu.

ErreurSymptômeSolution
Oublier le ;error: syntax error, unexpected …, expecting ';'Chaque option dans un attrset se termine par ;
Confondre [ ] et { }Erreur de type lors de l'évaluationsystemPackages attend une liste [ ], pas un attrset { }
Mettre un paquet là où une option est attendueA definition for option `services.nginx.enable' is not of type `boolean'services.nginx.enable = pkgs.nginx est faux, écrire = true
Oublier git add avant rebuild (configuration en flake)Path '…' in the repository … is not tracked by Gitgit add les nouveaux fichiers avant nixos-rebuild ; sans flake, Git n'intervient pas
Modifier system.stateVersionComportement imprévisible sur les données existantesNe jamais changer après l'installation initiale

Une erreur Nix se lit de haut en bas : la première ligne dit ce qui a échoué, les suivantes disent où. L'évaluateur pointe directement le fragment fautif avec un curseur ^, et --show-trace déplie la pile quand l'erreur vient d'un fichier importé. Voici un cas courant, une faute de frappe dans un nom de paquet écrit dans un bloc with pkgs; :

error: undefined variable 'gittt'
at /etc/nixos/configuration.nix:12:5:
11| environment.systemPackages = with pkgs; [
12| gittt
| ^
13| ];
  • undefined variable 'gittt', le nom n'existe ni dans pkgs ni ailleurs : faute de frappe probable. Écrit sous la forme pkgs.gittt, le même oubli donne attribute 'gittt' missing.
  • at …:12:5, ligne 12, colonne 5, le curseur est précis.
  • Correction : nix search nixpkgs git pour trouver le nom exact.

Première modularisation : diviser la configuration

Section intitulée « Première modularisation : diviser la configuration »

Dès que configuration.nix dépasse une cinquantaine de lignes, découpez-le en fichiers thématiques : chaque domaine d'administration y gagne un fichier que l'on relit d'un coup d'œil, et que l'on peut réutiliser sur une autre machine.

Le découpage utile suit les domaines d'administration, pas les types d'options : ce que vous cherchez quand vous revenez sur la machine, c'est « où sont déclarés les utilisateurs », pas « où sont les booléens ». configuration.nix reste le point d'entrée et ne garde que les options globales (bootloader, nom d'hôte, fuseau horaire) ; chaque fichier importé se suffit à lui-même et peut être copié tel quel sur une autre machine.

/etc/nixos/
├── configuration.nix ← entrée principale + options globales
├── hardware-configuration.nix
├── users.nix ← déclaration des utilisateurs
└── services/
└── ssh.nix ← configuration SSH

Chaque fichier extrait garde la même forme que configuration.nix : une fonction qui reçoit { config, pkgs, ... }: et retourne un attrset d'options. Ce n'est pas une exigence de style, c'est ce qui permet à l'évaluateur de fusionner tous les fichiers en une seule configuration. Ici, seul le domaine utilisateurs est déclaré.

{ config, pkgs, ... }:
{
users.users.admin = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."
];
};
}

Le durcissement SSH part dans son propre fichier, sous un sous-dossier services/. L'intérêt devient évident dès la deuxième machine : ce fichier est le contrat de sécurité de votre accès distant, vous le relisez en une fois au lieu de le chercher au milieu de cinquante lignes d'options sans rapport.

{ config, pkgs, ... }:
{
services.openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
PermitRootLogin = "no";
};
};
}

Le fichier d'entrée maigrit : il ne contient plus que la liste imports et les options qui n'appartiennent à aucun domaine particulier. Les chemins sont relatifs au fichier courant (./services/ssh.nix), pas au répertoire de travail, et Nix refuse un chemin inexistant au moment de l'évaluation.

{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./users.nix
./services/ssh.nix
];
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "serveur-prod";
time.timeZone = "Europe/Paris";
environment.systemPackages = with pkgs; [
git vim curl htop
];
system.stateVersion = "26.05";
}

nixos-rebuild switch évalue tous les fichiers listés dans imports comme s'ils n'en formaient qu'un seul. Concrètement, deux fichiers qui donnent à la même option deux valeurs différentes provoquent l'erreur The option `networking.hostName' has conflicting definition values à l'évaluation ; deux valeurs identiques passent sans bruit. Les options de type liste (environment.systemPackages, imports) font exception : le système de modules concatène leurs définitions, et deux fichiers peuvent chacun ajouter leurs paquets. Ce comportement suffit à couvrir la majorité des configurations mono-machine.

Ce tableau se lit par la colonne Vérification : elle donne la commande qui tranche entre plusieurs causes possibles avant de toucher au fichier. Le réflexe utile sur NixOS est de séparer deux familles de pannes. Les trois premières lignes bloquent l'évaluation ou la construction, le système n'a pas bougé et le retour arrière est immédiat. Les trois dernières surviennent après activation : le nouveau profil est en place, et l'entrée précédente reste sélectionnable au démarrage pour revenir à l'état qui fonctionnait.

ErreurCause probableVérificationSolution
error: syntax error; manquant ou accolade non ferméeLigne indiquée dans le message d'erreurVérifier ; en fin d'option, { } équilibrés
undefined variable 'xxx' ou attribute 'xxx' missingPaquet ou option inexistantenix search nixpkgs xxx ou nixos-option xxxCorriger le nom ou trouver l'option équivalente
nixos-rebuild switch semble bloquéBuild de dépendances volumineuxRelancer avec --print-build-logs (-L) pour voir les journaux de buildAttendre, première activation peut être longue
Failed to start sshd.serviceConfiguration SSH invalide ou port déjà utilisésystemctl status sshd + journalctl -u sshdVérifier services.openssh.settings, port 22 libre
Service absent après rebuildOption enable = false ou non déclaréenixos-option services.xxx.enableAjouter ou corriger l'option dans la config
error: path '/etc/nixos/hardware-configuration.nix' does not existFichier manquant dans le chemin importéls /etc/nixos/Regénérer avec sudo nixos-generate-config
  • configuration.nix est une fonction Nix, elle reçoit config et pkgs, et retourne un attrset d'options NixOS.
  • Paquet (environment.systemPackages) et option service (services.xxx.enable) sont deux mécanismes distincts, les modules NixOS font les deux à la fois, ne doublez pas.
  • Utilisez search.nixos.org/options ou nixos-option localement pour trouver la bonne option.
  • nixos-rebuild dry-build valide sans rien construire ni appliquer, utilisez-le systématiquement avant switch.
  • system.stateVersion ne se modifie jamais après l'installation initiale.
  • La modularisation avec imports = [ ./fichier.nix ] est simple et efficace, découpez tôt.

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn