# Configuration NixOS au Crans Voici la configuration NixOS du Crans. Les fichiers `README.md` des différents dossiers devraient indiquer assez précisément le rôle du dossier (et si ce n'est pas le cas, fais de la doc !). **Table des matières** 1. [`Nix` et `NixOS`](#nix-et-nixos) 1. [`Nix`](#nix) 2. [`NixOS`](#nixos) 3. [`Nix Store`](#nix-store) 4. [`Flakes`](#flakes) 2. [Rôles des fichiers et sous-dossiers](#rôles-des-fichiers-et-sous-dossiers) 1. [Fichiers `flake`](#fichiers-flake) 2. [Secrets](#secrets) 3. [Machines](#machines) 4. [Modules](#modules) 5. [Devshells](#devshells) 3. [Commandes utiles](#commandes-utiles) 1. [Commandes pour les flakes](#commandes-pour-les-flakes) 2. [Commandes pour NixOS](#commandes-pour-nixos) 3. [Commandes pour les devshells](#commandes-pour-les-devshells) 4. [Commandes pour le Nix Store](#commandes-pour-le-nix-store) ## Nix et NixOS Voici une petite introduction de ce que sont `nix` et `NixOS`. Le but n'est pas de faire un véritable tutoriel mais plutôt faire des rappels qui peuvent toujours être utiles (ou pour les nouveaux et nouvelles apprenti⋅e⋅s !). [`NixOS`](https://nixos.org/) est une distribution Linux basé sur une configuration **déclarative**, permettant ainsi une **reproducibilité**. Cette configuration est écrite dans le langage [`nix`](https://nixos.org/manual/nix/stable/language/index.html). N'ayez pas peur de ce langage, on peut le décrire comme une version plus expressive du JSON (avec des variables, des fonctions, ...). ### Nix En lisant quelques fichiers de configuration, vous devriez rapidement comprendre la syntaxe de `nix` (qui n'est pas très complexe). Voici une liste non exhaustive de subtilités que vous pouvez rencontrer dans la configuration NixOS du Crans qu'il faut avoir en tête en lisant du code `nix` : * `nix` est typé et, dans la grande majorité des cas, ne pourra pas être exécuté si les types ne sont pas respectés. Les types les plus importants sont : les nombres (ex : `1`), les chaînes de caractères (ex : `"toto1234"`), les listes (ex d'une liste de nombres : `[ 1 10 1234 ]`, attention il n'y a pas de séparateur entre les éléments), les ensembles (ex : `{ a = "foo"; b = 3; }`), et les fonctions (ex : `x: x + 1` qui correspond à une fonction qui à `x` associe `x + 1`). Vous trouverez plus de détails [sur cette page](https://nixos.org/manual/nix/stable/language/values). * Les codes `a.b = 3;` et `a = { b = 3; };` sont sémantiquement équivalents : cela signifie que vous pouvez changer l'un en l'autre et réciproquement. Usuellement, la première version n'est utilisé que lorsque `a` n'a qu'un seul attribut. * La variable `config` contient toute la configuration actuelle : elle permet d'utiliser des valeurs déclarées dans un autre fichier et susceptibles d'être modifiées dans le futur sans que cela ne pose de problème. Cela sera très utile notamment pour `age` (voir [secrets/README.md](secrets/README.md)). * Lorsque vous importez d'autres fichiers avec `imports`, vous ne pouvez qu'importer des fichiers. Si vous importez un dossier, cela n'aura pour effet que d'importer le fichier `default.nix` du dossier importé. ### NixOS `NixOS` se construit (*build* en anglais) sous forme de dérivations (voir [la partie sur le `Nix Store`](#nix-store) pour plus d'explications). Celles-ci contiennent l'intégralité de la configuration au moment du build, ce qui est forcé par le fait que l'évaluation se fait de façon pure, c'est-à-dire qu'il n'est pas possible d'utiliser des éléments en dehors de la configuration pour écrire la configuration. Cela est forcé par l'utilisation des `flakes` (voir [la partie consacrée aux `flakes`](#flakes)). Dans cette configuration, et grâce à l'utilisation des `flakes`, il est possible d'écrire la configuration de plusieurs machine dans ce même dépôt git. Chaque machine sous `NixOS` aura donc le code de chaque autre machine inscrite dans la configuration, mais du fait que **nix s'évalue de manière paresseuse**, chaque machine n'évaluera et ne compilera que ce qui est nécessaire pour sa propre configuration. Pour trouver des options pour décrire la configuration d'une machine, rendez-vous sur le saint graal de `nixpkgs` (le dépôt contenant tous les logiciels et librairies packagés pour `nix`, le package manager du même nom que le langage), et de `NixOS` : https://search.nixos.org/. Vous pouvez également trouver de l'aide pour la configuration de services sur https://nixos.wiki/. ### Nix Store Le `Nix Store` est une abstraction permettant de stocker **de manière immuable** des données utiles au package manager `nix` et à `NixOS` (comme les dérivations, les sources de packages, les packages eux-mêmes, ...). On peut découper le `Nix Store` en plusieurs parties, les principales étant le dossier `/nix/store` en local, ou les différents caches contenant des binaires pour éviter la recompilation de tous les packages (le principal étant situé à https://cache.nixos.org). Il est important de noter que **`/nix/store` est un dossier monté en lecture seule et est visible par tous les utilisateurices**. Il est donc crucial de **ne jamais laisser apparaître de mot de passe en clair dans cette configuration**, car celui-ci serait alors lisible par tous les utilisateurices ayant accès à la machine. L'utilisation de `Sops` (voir [secrets/README.md](secrets/README.md)) permet de palier ce problème en introduisant des secrets chiffrés uniquement accessibles pour les machines devant y avoir accès et pour les nounous. Bien que ce que les fonctionnalités de Nix exposées dans cette documentation sont pures, Nix a besoin d'un état interne. Les fichiers **stateful** de `Nix` se trouvent dans le dossier `/nix/var`. Ce dossier contient notamment les logs de `Nix`, ainsi qu'une base de donnée Sqlite, les profiles `Nix`, *etc.* Certains de ces fichiers ne sont pas primordiaux (*e.g.* les logs), mais d'autres le sont. Par exemple, la BDD (accessible au chemin suivant : `/nix/var/db/db.sqlite`) est nécessaire au bon fonctionnement de `Nix`. Une corruption de cette BDD peut entrainer le dysfonctionnement du système (*e.g.* ne plus pouvoir faire de maj). ### Flakes Le fichier [`flake.nix`](flake.nix) dénote de tous les autres fichiers de cette configuration : celui-ci est une `flake`, à savoir l'unité de permettant de packager du code `nix` de manière reproducible. Plus simplement, dans notre cas, cette `flake` contient toutes les sources utilisées dans la configuration pour pouvoir être évaluée, ainsi que toutes les sorties, à savoir les configurations de toutes les machines, ainsi que les shells de développement (voir [la partie sur les `devshells`](#devshells)). ## Rôles des fichiers et sous-dossiers ### Fichiers flake Les fichiers [`flake.nix`](flake.nix) et [`flake.lock`](flake.lock) sont respectivement la [`flake`](#flakes) de cette configuration et le *lockfile* associé. Le lockfile est généré automatiquement par certaines commandes et ne doit pas être modifié à la main : il s'agit, à la manière d'un `Cargo.lock` pour Rust ou d'un `package-lock.json` pour Node.js, d'un fichier décrivant précisément les versions des dépendances utilisées pour compiler/exécuter le projet. ### Secrets Le fichier [`secrets.nix`](secrets.nix) contient la description des secrets et des clefs GPG utilisées par `age`, tant par les machines que par les nounous. Le dossier [`secrets`](secrets) contient tous les secrets nécessaires aux machines lors de la construction de leur configuration. Vous pouvez voir plus de détails dans [`secrets/README.md`](secrets/README.md). ### Machines Le dossier [`hosts`](hosts) contient la configuration unique à chaque machine. On y retrouve en particulier le bootloader, le déchiffrement des secrets nécessaires pour la machine et la configuration réseau. En effet, il est utile de rappeler qu'aucune machine du Crans (hors VM adhérent⋅e⋅s) n'utilise du DHCP : il est donc nécessaire d'écrire à la main toutes les interfaces dont elles disposent. Pour plus de détails sur les interfaces réseaux, vous pouvez vous réferer à la [documentation des VLAN](https://gitlab.crans.org/nounous/documentation/-/blob/master/infrastructure/plan.md), et à [`hosts/README.md`](hosts/README.md) de manière plus générale. ### Modules Le dossier [`modules`](modules) contient l'ensemble des options qui peuvent être partagées par plusieurs configurations de machines. Vous pouvez voir plus de détails dans [`modules/README.md`](modules/README.md). ### Devshells Le dossier [`devshells`](devshells) contient des environnements de travails pouvant être utilisés par tout utilisateurice. Ceux-ci permettent d'ajouter temporairement des paquets à l'environnement de travail (dont le shell bash ou équivalent), permettant ainsi d'avoir facilement (voir [la partie sur les commandes liées aux devshells](#commandes-pour-les-devshells)) tous les outils nécessaires au développement/débuggage. Vous pouvez voir plus de détails dans [`devshells/README.md`](devshells/README.md). ## Commandes utiles Pour toutes les commandes présentées, on débutera la ligne de commande par `$` si tout utilisateurice peut l'exécuter, et `#` s'il faut les droits super-user. ### Commandes pour les flakes - Vérification de la validité de la flake ```bash $ nix flake check [path] ``` - Mise à jour d'une dépendance dans la flake (mettra à jour le lockfile) ```bash $ nix flake lock --update-input [input name] ``` - Mise à jour de toutes les dépendances de la flake (mettra à jour le lockfile) ```bash $ nix flake update ``` ### Commandes pour NixOS - Regénération de la configuration **sans modifier la configuration**, utile pour tester une configuration ```bash $ nixos-rebuild dry-build ``` - Regénération de la configuration **en remplaçant la configuration courante** (ne fera rien si la configuration contient des erreurs) ``` # nixos-rebuild switch ``` ### Commandes pour les devshells - Utilisation d'un devshell ```bash $ nix develop [url] ``` Par exemple, pour utiliser le devshell par défaut et que cette configuration est située dans `/etc/nixos`, la commande pourra être : `nix develop /etc/nixos#default`. Vous pouvez par ailleurs omettre `#default`, et sans dossier indiqué le dossier courant sera utilisé, on peut donc écrire `nix develop` pour utiliser le devshell par défaut si le dossier courant est `/etc/nixos`. ### Commandes pour le Nix Store - Supprimer toutes les entrées du Nix Store non utilisées ```bash $ nix-store --gc # "gc" pour garbage collect ``` - Supprimer toutes les objets non atteignables dans le Nix Store ``` # nix-collect-garbage -d ``` - Optimiser les liens symboliques dans le Nix Store (permet de gagner de l'espace de stockage) ```bash $ nix-store --optimise ```