Déploiement de vos configurations NixOs avec Colmena
Table des matières
Pourquoi utiliser Colmena
Dans l'article précédent, vous avez installé NixOS sur votre machine OVH. Une fois terminé, vous avez
pu modifier la configuration et la déployer sur la machine avec la commande nixos-rebuild:
Dans l'utilisation de tous les jours, cela présente plusieurs inconvénients:
- C'est une longue ligne de commande.
- Si vous placez la configuration de plusieurs machines dans le
flake.nix, alors il faut bien faire attention à ne pas déployer par erreur sur la mauvaise machine. C’est-à-dire ne pas déployer par exemple.#machine1surutilisateur@machine2.example.com. - Vous ne pouvez pas déployer en masse sur plusieurs machines, ce qui est gênant si vous en avez beaucoup.
Dans cet article je vous propose d'utiliser l'outil Colmena pour gérer vos configurations et déploiements. Colmena est un outil parmis d'autres pour le déploiement de machines NixOS, vous pouvez en trouver une liste sur le Wiki NixOS.
Avec Colmena la ligne nixos-rebuild ci-dessus devient:
Détail de la commande.
apply- travailler sur une machine distante.
apply-locallui permet de gérer le configuration de votre poste. --on nommachine- Selection des machines à déployer. On peut y indiquer plusieurs machines ou bien des tags (Exemple: "@web").
--impure- Indique que colmena doit évaluer les fichiers même s'ils sont modifiés dans Git. Utile seulement pendant le développement d'une configuration.
Présentation de Colmena
Colmena est un des nombreux logiciels de déploiement de configuration NixOS sur des machines distantes. Je le présente ici, car je l'utilise, mais d'autres existent comme NixOps et Morph.
Colmena possède ces fonctionnalités:
- Ajout de tags à vos machine pour pouvoir déployer tous les serveurs web par exemple.
- Gestion des secrets, c’est-à-dire téléversement des fichiers contenant des secrets vers la machine distante lors du déploiement de configuration (évite leur présence dans le magasin Nix qui est en lecture pour tous !).
- Extraction de données depuis la configuration, par exemple pour obtenir tous les noms des machines et leurs IPs telle qu'elles apparaissent. (Utile pour renseigner une zone DNS par exemple).
- Déploiement en parallèle de plusieurs machines.
- Construction et téléchargement des configurations sur les machines distantes pour éviter que votre poste de travail ne téléverse les mêmes fichiers vers plusieurs machines distantes.
Prérequis
Vous avez besoin d'une configuration NixOS sous forme de flake, celle construite à l'article précédent par exemple, dans le cas contraire, adaptez les exemples.
Personnalisation des exemples de codes donnés
Tout au long de l'article, vous pourrez entrer les valeurs correspondantes à votre situation dans des cases de formulaire. Les exemples de code de l'article utiliseront vos valeurs pour pouvoir être utilisés directement. La modification est faite en local avec Javascript, aucune donnée n'est envoyée nulle part.
Sinon vous pouvez simplement adapter les exemples suivant votre cas.
Modifications sur les fichiers
Pour déployer une machine avec Colmena vous devez copier sa configuration depuis la production du flake nixosConfigurations vers la production colmena. Il faut aussi
ajouter l'outil colmena à l'environement shell. En outre, vous allez déplacer les fichiers de configuration de votre machine vers un sous-répertoire
hosts pour pouvoir en ajouter d'autres ensuite sans encombrer le répertoire racine du flake. La structure finale sera:
|- flake.nix
|- hosts
|- nommachine
| |- configuration.nix
| |- disk.nix
| |- hardware.nix
|- autremachine
| |- configuration.nix
| |- disk.nix
| |- hardware.nix
Vous pouvez renseigner ci-dessous le nom de votre machine et son adresse ainsi que l'utilisateur à utiliser pour s'y connecter en SSH. L'utilisateur SSH doit pouvoir faire du sudo sans entrer de mot de passe, donc protégez bien sa clé SSH privée:
Modifiez vos fichiers comme suit:
-
Créez le répertoire hosts/nommachine et déplacez
configuration.nix,disk.nixethardware.nixvers le répertoire de la machine. (N'oubliez pas d'utilisergit mvsi vos fichiers sont dans un dépôt.) -
Le fichier
flake.nixdoit être modifié. Voir plus bas pour les détails.flake.nix
{ description = "Mes machines NixOS"; # Entrées utilisées. inputs = { # NixOS et ses paquets. nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; # Disko, le module de partitionnement disque. disko = { url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; }; # Productions du flake. Ici ce sera un environement shell, la machine nixosSystem et la # configuration dans Colmena. outputs = { self, nixpkgs, disko, ... }: let # On récupère les paquets x86_64-linux dans nixpkgs. system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; }; lib = nixpkgs.lib; # Fonction créant un nixosSystem avec les valeurs supplémentaires necessaires. # Cette fonction prend en argumant un nom de machine et va l'utiliser pour # récupérer les valeurs necessaires depuis l'ensemble d'attributs "servers" # défini plus bas. customNixosSystem = name: let # Equivalent a modules = servers."${name}".modules. inherit (servers."name") modules; in lib.nixosSystem { inherit system; # Equivalent à modules = modules. Les modules (configuration.nix, etc..) définissant # la configuration de la machine. inherit modules; }; # Fonction créant un noeud (=une machine) dans colmena colmenaNode = name: let # Equivalent a colmena = servers."${name}".colmena, etc. inherit (servers."name") colmena modules; in { ... }: # On récupère les attributs pour colmena définits dans "servers" plus bas. # et on les fussionne à l'ensemble d'attributs restant. "//" est l'opérateur de # fusion entre ensemble d'attributs. # Au final "deployment" par exemple se retrouve aux cotés de "imports" dans les attributs. colmena // { # "modules" doit être nommé "imports" quand il apparaît dans un module de confiuration de m # machine comme ici. imports = modules; }; # On définit les machines ici. Ces valeurs seront utilisées dans nixosConfiguration et colmena. # "modules" deviendra "imports" dans colmena car c'est ce qu'il attends. # Pour chaque machine, on défini les arguments spécifiques comme reserveZFS et hostId. # Et la liste des modules. servers = { nommachine = { # Les attributs à passer à colmena. colmena = { # On défini l'adresse de la machine ici, c'est ce qui permet ne ne pas avoir à l'indiquer # sur la ligne de commande colmena. deployment.targetHost = "addrmachine"; # On défini l'utilisateur avec lequel se connecter en SSH à la machine. # L'utilisateur doit avoir le droit de lancer des commandes sudo sans mot de passe. deployment.targetUser = "nomutilisateur"; # Travailler et télécharger les paquets depuis la machine distante. Equivalent de # `--build-host` pointant sur la machine distante dans la commande nixos-rebuild. deployment.buildOnTarget = true; # Tags Colmena, pour déployer sur tout un groupe de machine par la suite. deployment.tags = [ "web" "ovh" ]; }; # Les modules constituant la configuration de la machine. modules = [ # Mettre a dispo les définition disko dans la configuration. disko.nixosModules.disko # Fichier contenant la configuration hardware. ./hosts/nommachine/hardware.nix # Fichier décrivant le partitionnement et les systèmes de fichiers. # Après installation de la machine, il est utilisé pour définir les systèmes de fichier # qui doivent être montés au démarrage. ./hosts/nommachine/disk.nix # Configuration NixOS de la machine. ./hosts/nommachine/configuration.nix ]; }; }; in { # Définir un environement shell contenant l'outil nixos-anywhere pour installer la machine. # On y ajoute colmena pour les déploiements. devShells.x86_64-linux.default = pkgs.mkShell { packages = with pkgs; [ colmena nixos-anywhere ]; }; # Définition de votre machine dans nixosConfigurations. On le garde ici pour les déploiement # futurs avec nixos-anywhere si vous souhaitez le réinstaller un jour. nixosConfigurations.nommachine = customNixosSystem "nommachine"; # Configuration de colmena et définition des machines. colmena = { # La section meta s'applique à toutes les machines meta = { nixpkgs = import nixpkgs { inherit system; }; }; # On défini chaque machine ici, en utilisant les configurations définie plus haut. nommachine = colmenaNode "nommachine"; }; }; }
Modifications faites sur flake.nix
Au lieu de placer la configuration de notre machine dans nixosSystem ou bien colmena, on la place dans un ensemble d'attributs (attrset en anglais) nommé
«servers». Il contiendra pour chaque machine deux ensembles "colmena" et "modules". Dans l'exemple on ajoute aussi deux tags pour découvrir cette fonctionnalité Colmena.
servers = {
nommachine = {
colmena = {
deployment.targetHost = "addrmachine";
deployment.targetUser = "nomutilisateur";
deployment.buildOnTarget = true;
deployment.tag = [ "web" "ovh" ];
};
# Les modules constituant la configuration de la machine.
modules = [
disko.nixosModules.disko
./hosts/nommachine/hardware.nix
./hosts/nommachine/disk.nix
./hosts/nommachine/configuration.nix
];
};
};
-
colmena- Les attributs colmena, dans notre cas la valeur pour
deployment.targetHostqui indique le domaine ou l'IP de la machine, l'utilisateur SSH dansdeployment.targetUser(vous pouvez retirer la ligne si vous utilisez root), et une configuration indiquant de faire le build sur la machine. Les autres configurations possibles sont décrites dans la documentation de Colmena.
-
modules- La liste des modules composant la configuration de la machine, c’est-à-dire les fichiers nix présents dans son répertoire.
Une fonction est définie pour transformer ces valeurs en nixosSystem. On amène les valeurs pour modules dans la portée locale de la fonction,
puis on construit le système avec ces valeurs en les plaçant dans l'ensemble d'attributs passés en argument à la fonction nixosSystem.
customNixosSystem = name:
let
inherit (servers."name") modules;
in lib.nixosSystem {
inherit system;
inherit modules;
};
au final cette fontion retourne ceci:
lib.nixosSystem {
inherit system;
# Les modules composant la configuration de la machine, lui aussi venant de `servers`.
modules = [
disko.nixosModules.disko
./hosts/nommachine/hardware.nix
etc.
];
};
Une fonction est définie pour transformer ces valeurs en noeud Colmena. Un noeud colmena est un module, on le voit à son argument {...}. La différence
avec l'ensemble d'attributs de nixosSystem est que modules devient imports.
L'ensemble d'attributs colmena est fusionné au reste pour que tout ce qui est dedans se retrouve au même niveau que imports.
colmenaNode = name:
let
inherit (servers."name") colmena modules;
in {...}:
colmena // {
imports = modules;
};
au final cette fontion retourne ceci:
{...}: {
# Attributs de deployment Colmena récupérés dans `servers`.
deployment.targetHost = "addrmachine";
deployment.buildOnTarget = true;
imports = [
# Les modules dans `servers`.
disko.nixosModules.disko
./hosts/nommachine/hardware.nix
etc.
];
};
Le reste du fichier flake.nix définie un environnement shell, avec colmena disponible. Ensuite on définit les nixosConfiguration et noeuds
colmena en utilisant les deux fonctions vues précédemment.
nixosConfigurations.nommachine = customNixosSystem "nommachine";
colmena = {
meta = {
nixpkgs = import nixpkgs { inherit system; };
};
nommachine = colmenaNode "nommachine";
};
Déploiement de la configuration avec Colmena
Tout d'abord, entrez dans l'environnement shell du flake où la commande colmena est disponible:
Vous pouvez maintenant déployer votre configuration:
Détail de la commande.
apply- Travaille sur la configuration d'une machine distante.
apply-localest disponible pour déployer la machine sur laquelle vous lancez Colmena, par exemple si vous l'utilisez pour votre poste de travail. --on nommachine- Indique à Colmena les machines à déployer. Liste de noms séparés par des virgules, et vous pouvez utiliser '*', ex:
--on web-*,sql-*ou bien des tags, ex: '--on @web' --impure- Les flakes Nix nécessitent que les fichiers soit dans un dépot GIT. Cette option indique à Colmena de travailler même si certains fichiers ont été modifiés et non commités, dans le cas contraire il refuse.
switch- Pousse la configuration sur la machine et règle le boot pour démarrer dessus. Les autres commandes sont:
- build: construit seulement la configuration.
- push: pousser la configuration sans l'activer (copie des dérivations necessaires du magasin Nix sur la machine distante).
- boot: n'active pas la configuration mais configure le boot pour qu'elle soit lancée au prochain démarrage.
- test: active la configuration mais ne configure pas le boot. Idéal si vous travaillez sur la configuration réseau ; en cas de perte de connexion un reboot redémarre sur une configuration saine.
- dry-activate: Montre seulement ce qui serait fait.
Ou, en utilisant un nom de tag:
Lorsque colmena, tout comme nixos-rebuild, déploie la configuration, il fait en sorte qu'elle se lance au démarrage du serveur.
Donc lorsque vous travaillez sur la configuration réseau ou firewall de vos machines, utilisez toujours "test" à la place de "switch". En
cas de perte de la main sur votre machine, vous n'aurez qu'à la redémarrer dans l'interface OVH et elle démarrera sur l'ancienne configuration.
Dans le cas contraire vous devrez lancer une fenêtre KVM pour choisir au démarrage la configuration précédente.
Plus de risque de déployer la mauvaise configuration.
Ajout d'une autre machine dans Colmena
Pour ajouter une autre machine en utilisant l'article précédent, vous pouvez créer ses fichiers .nix (sauf flake.nix) dans un nouveau répertoire à son nom dans hosts/ puis l'ajouter dans la configuration flake dans l'ensemble
d'attributs servers, ainsi que colmena et nixosConfigurations. Exemple:
servers = {
nommachine = {
colmena = {
deployment.targetHost = "addrmachine";
deployment.targetUser = "nomutilisateur";
deployment.buildOnTarget = true;
deployment.tags = [ "web" "ovh" ];
};
modules = [
disko.nixosModules.disko
./hosts/nommachine/hardware.nix
./hosts/nommachine/disk.nix
./hosts/nommachine/configuration.nix
];
};
autremachine = {
colmena = {
deployment.targetHost = "autremachine.example.com";
deployment.targetUser = "nomutilisateur";
deployment.buildOnTarget = true;
deployment.tags = [ "bdd" "ovh" ];
};
modules = [
disko.nixosModules.disko
./hosts/autremachine/hardware.nix
./hosts/autremachine/disk.nix
./hosts/autremachine/configuration.nix
];
};
};
nixosConfigurations.nommachine = customNixosSystem "nommachine";
nixosConfigurations.autremachine = customNixosSystem "autremachine";
colmena = {
meta = {
nixpkgs = import nixpkgs { inherit system; };
};
nommachine = colmenaNode "nommachine";
autremachine = colmenaNode "autremachine";
};
la commande d'installation nixos-anywhere fonctionnera à l'identique. Mais il ne faut pas oublier de lui dire d'écrire le fichier hardware.nix dans le
sous répertoire.
Conclusion
Vous pouvez maintenant gérer la configuration de votre machine NixOS plus comfortablement, et vous pouvez aussi en ajouter d'autres à votre flake sans risquer de faire des erreurs.