Vous avez des flakes, des devShells, un flake.lock qui verrouille chaque dépendance. Maintenant, comment en faire un usage d’équipe concret ? Ce guide transforme les briques des guides 8 à 10 en six cas pratiques opérationnels : poste de travail standardisé, CI/CD identique au local, checks automatisés, build reproductible d’un outil interne, stratégie de mise à jour et onboarding express. Chaque exemple s’appuie sur la même flake.nix de référence, directement utilisable dans un projet réel.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Construire un devShell d’équipe embarquant Terraform, Ansible, kubectl, Helm et les outils de qualité
- Consommer ce devShell dans GitHub Actions et GitLab CI — sans configuration supplémentaire
- Définir des checks reproductibles (lint, format) exécutés localement et en CI avec
nix flake check - Empaqueter un script d’administration comme dérivation Nix reproductible avec
writeShellApplication - Gérer les mises à jour de
flake.locksans surprises pour l’équipe - Ramener l’onboarding d’un nouveau membre à
git clone+nix develop
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Nix devient particulièrement utile dès qu’une équipe est impliquée :
- Deux ingénieurs ont des versions différentes de Terraform ou d’Ansible — les plans divergent
- La CI installe des paquets avec
sudo apt installdans le pipeline, créant des builds fragiles et lents - Un nouveau contributeur passe une demi-journée à installer l’outillage avant d’écrire la première ligne
- Une mise à jour silencieuse de
helmen CI casse le déploiement — impossible de reproduire localement - Les scripts shell sont valides “sur ma machine” mais pas sur le runner
Un flake.nix versionné avec le code résout structurellement chacun de ces problèmes.
Prérequis
Section intitulée « Prérequis »Ce guide fait suite aux guides 8 (environnements), 9 (factorisation) et 10 (flakes). Vous devez :
- avoir Nix installé avec les flakes activés (voir le guide d’installation),
- comprendre la structure d’un
flake.nix(inputs, outputs, devShells), - savoir utiliser
nix developetnix flake check.
Structure du projet de référence
Section intitulée « Structure du projet de référence »Créez ce projet dans votre répertoire de lab. Tous les cas pratiques utilisent cette même base :
mkdir -p ~/Projets/lab-nix && cd ~/Projets/lab-nixmkdir -p nix scripts srcgit initRépertoirelab-nix/
- flake.nix (point d’entrée — inputs + délégation aux modules)
- flake.lock (révisions verrouillées — toujours commité dans Git)
Répertoirenix/
- devshells.nix (devShell d’équipe)
- checks.nix (vérifications automatisables)
- packages.nix (builds reproductibles)
Répertoirescripts/
- lint.sh (lint shell)
- validate.sh (validation Terraform)
Répertoiresrc/ (code source)
- …
- .envrc (activation automatique avec direnv — optionnel)
Le flake.nix racine reste court grâce à la factorisation dans nix/. C’est la convention introduite dans le guide 9.
{ description = "Boîte à outils DevOps — reproductible pour toute l'équipe";
inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; flake-utils.url = "github:numtide/flake-utils"; };
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; src = ./.; in { devShells.default = import ./nix/devshells.nix { inherit pkgs; }; checks = import ./nix/checks.nix { inherit pkgs src; }; packages = import ./nix/packages.nix { inherit pkgs; }; } );}Cas pratique 1 — Boîte à outils DevOps standardisée
Section intitulée « Cas pratique 1 — Boîte à outils DevOps standardisée »L’objectif
Section intitulée « L’objectif »Un devShell unique qui embarque tout l’outillage d’une équipe DevOps. Chaque membre entre dans cet environnement avec nix develop et obtient les mêmes versions, peu importe sa distribution ou son historique d’installation.
{ pkgs }:
pkgs.mkShell { name = "devops-toolkit";
packages = with pkgs; [ # Contrôle de version git git-crypt
# Traitement de données structurées jq yq-go
# Qualité de code shell shellcheck shfmt
# Infrastructure as Code terraform opentofu
# Gestion de configuration ansible ansible-lint
# Kubernetes kubectl helm kustomize k9s
# Sécurité trivy cosign
# Debug réseau curl httpie ];
shellHook = '' echo "Environnement DevOps actif ($(uname -m))" echo " Terraform : $(terraform version 2>/dev/null | head -1)" echo " kubectl : $(kubectl version --client 2>/dev/null | head -1)" echo " Helm : $(helm version --short 2>/dev/null)" echo " Ansible : $(ansible --version 2>/dev/null | head -1)" '';}cd ~/Projets/lab-nixgit add flake.nix nix/devshells.nixnix developEnvironnement DevOps actif (x86_64-linux) Terraform : Terraform v1.11.4 kubectl : Client Version: v1.31.4 Helm : v3.17.2+g4a5b5ed Ansible : ansible [core 2.18.2]Cas pratique 2 — CI/CD identique au poste local
Section intitulée « Cas pratique 2 — CI/CD identique au poste local »Le principe
Section intitulée « Le principe »Votre flake.nix est versionné avec le code. La CI le consomme directement avec la même commande qu’en local :
# En localnix develop --command bash -c "shellcheck scripts/*.sh && terraform -chdir=infra validate"
# En CI — exactement la même commandenix develop --command bash -c "shellcheck scripts/*.sh && terraform -chdir=infra validate"name: CI
on: [push, pull_request]
jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- uses: cachix/install-nix-action@v31 with: github_access_token: ${{ secrets.GITHUB_TOKEN }} extra_nix_config: | experimental-features = nix-command flakes
# Cache binaire — réduit drastiquement le temps de téléchargement - uses: cachix/cachix-action@v16 with: name: my-org-cache authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Vérification de la structure du flake run: nix flake check --no-build
- name: Lint et validation IaC run: | nix develop --command bash -c " shellcheck scripts/*.sh terraform -chdir=infra validate ansible-lint playbooks/ || true "image: nixos/nix:2.24.10
variables: NIX_CONFIG: "experimental-features = nix-command flakes\naccept-flake-config = true"
# Cache le store Nix entre les jobs du même runnercache: key: nix-store-${CI_RUNNER_ID} paths: - /nix/store policy: pull-push
stages: - validate - test
flake-check: stage: validate script: - git config --global --add safe.directory "$CI_PROJECT_DIR" - nix flake check --no-build
lint: stage: validate script: - nix develop --command shellcheck scripts/*.sh
validate-iac: stage: test script: - nix develop --command terraform -chdir=infra validate - nix develop --command ansible-lint playbooks/ || trueSur un runner persistant, installez Nix une seule fois. Le store /nix est partagé entre tous les jobs — plus de re-téléchargement.
# Installation multi-utilisateur sur le serveur de CIsh <(curl -L https://nixos.org/nix/install) --daemon
# Activer les flakes pour l'utilisateur CImkdir -p /home/ci-runner/.config/nixecho "experimental-features = nix-command flakes" \ >> /home/ci-runner/.config/nix/nix.confLe premier job peuple le store (2-5 minutes). Les suivants réutilisent les paquets déjà présents (< 30 secondes pour nix develop).
Cas pratique 3 — Checks reproductibles avec nix flake check
Section intitulée « Cas pratique 3 — Checks reproductibles avec nix flake check »L’objectif
Section intitulée « L’objectif »Définir des vérifications (lint, format) comme des dérivations Nix :
- exécutables en local avec
nix flake check, - intégrées automatiquement en CI,
- mises en cache — un check déjà réussi ne retourne pas.
Définir les checks
Section intitulée « Définir les checks »{ pkgs, src }:
{ # Vérification des scripts shell shellcheck = pkgs.runCommandLocal "check-shellcheck" { buildInputs = [ pkgs.shellcheck ]; } '' find ${src}/scripts -name "*.sh" -exec shellcheck {} + touch $out '';
# Format des fichiers Nix (RFC-style) nixfmt = pkgs.runCommandLocal "check-nixfmt" { buildInputs = [ pkgs.nixfmt-rfc-style ]; } '' nixfmt --check ${src}/flake.nix find ${src}/nix -name "*.nix" -exec nixfmt --check {} + touch $out '';}Exécuter les checks
Section intitulée « Exécuter les checks »cd ~/Projets/lab-nixgit add nix/checks.nix scripts/
# Tous les checksnix flake check
# Un seul check, avec trace détaillée si erreurnix build .#checks.x86_64-linux.shellcheck --show-tracechecking flake output 'checks.x86_64-linux.shellcheck'...checking flake output 'checks.x86_64-linux.nixfmt'...Si shellcheck détecte un problème :
checking flake output 'checks.x86_64-linux.shellcheck'...error: builder for '/nix/store/...-check-shellcheck.drv' failed with exit code 1 scripts/lint.sh:12:5: warning [SC2086]: Double quote to prevent globbing and word splitting.Intégration CI
Section intitulée « Intégration CI »En GitLab CI et GitHub Actions, remplacez vos scripts de lint ad hoc par :
nix flake checkC’est une seule commande, indépendante du runner, qui exécute exactement les mêmes vérifications qu’en local.
Cas pratique 4 — Build reproductible d’un outil interne
Section intitulée « Cas pratique 4 — Build reproductible d’un outil interne »L’objectif
Section intitulée « L’objectif »Empaqueter un script d’administration comme dérivation Nix. Le binaire résultant est identique bit à bit sur toutes les machines. Il peut être distribué via un cache binaire ou installé directement avec nix profile install.
Exemple : script d’audit Kubernetes
Section intitulée « Exemple : script d’audit Kubernetes »{ pkgs }:
{ # Outil d'audit Kubernetes avec ses dépendances exactes embarquées k8s-audit = pkgs.writeShellApplication { name = "k8s-audit"; runtimeInputs = with pkgs; [ kubectl jq ]; text = '' echo "=== Noeuds du cluster ===" kubectl get nodes -o json \ | jq -r '.items[] | "\(.metadata.name)\t\(.status.conditions[] | select(.type=="Ready") | .status)"'
echo "" echo "=== Pods non Running ===" kubectl get pods --all-namespaces \ --field-selector 'status.phase!=Running,status.phase!=Succeeded' \ 2>/dev/null || echo "(aucun)"
echo "" echo "=== Événements Warning récents ===" kubectl get events --all-namespaces \ --field-selector type=Warning \ --sort-by='.lastTimestamp' \ 2>/dev/null | tail -15 ''; };}Construire, tester, distribuer
Section intitulée « Construire, tester, distribuer »cd ~/Projets/lab-nixgit add nix/packages.nix
# Construirenix build .#k8s-audit
# Tester (le binaire est dans ./result/bin/)./result/bin/k8s-audit
# Utiliser temporairement sans installernix shell .#k8s-audit --command k8s-audit
# Installer dans le profil utilisateurnix profile install .#k8s-auditLe binaire k8s-audit embarque ses propres versions de kubectl et jq depuis le store Nix — il fonctionne sur n’importe quelle machine avec Nix installé, sans dépendances système.
Cas pratique 5 — Stratégie de mise à jour de flake.lock
Section intitulée « Cas pratique 5 — Stratégie de mise à jour de flake.lock »Le problème
Section intitulée « Le problème »flake.lock fige la révision de nixpkgs. Il doit être mis à jour régulièrement pour obtenir les correctifs de sécurité et les nouvelles versions d’outils — sans casser l’équipe au passage.
Workflow de mise à jour
Section intitulée « Workflow de mise à jour »-
Créer une branche dédiée
Fenêtre de terminal git checkout -b chore/nix-update-$(date +%Y-%m) -
Mettre à jour toutes les dépendances
Fenêtre de terminal nix flake updateCela recrée
flake.lockavec les révisions les plus récentes de chaque input déclaré. -
Inspecter ce qui a changé
Fenêtre de terminal git diff flake.lock"lastModified": 1739000000,"lastModified": 1744823519,"rev": "d78a5c8a34f5b7e0c4d2e1f3a6b8c9e0f","rev": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",La révision de
nixpkgsest la seule vraie information. Consultezgithub.com/NixOS/nixpkgs/compare/<ancienne-rev>...<nouvelle-rev>pour voir les changements inclus. -
Valider localement
Fenêtre de terminal nix flake checknix develop --command bash -c "terraform version && kubectl version --client" -
Ouvrir une PR/MR
La CI valide les checks automatiquement. La PR est fusionnée si tout est vert.
-
Rollback si problème
Fenêtre de terminal # Revenir simplement à la révision précédente de nixpkgsgit revert HEAD# Ou épingler une révision spécifiquenix flake lock --update-input nixpkgs \--override-input nixpkgs \"github:nixos/nixpkgs?rev=d78a5c8a34f5b7e0c4d2e1f3a6b8c9e0f"
Cadence recommandée
Section intitulée « Cadence recommandée »| Fréquence | Cas d’usage |
|---|---|
| Hebdomadaire | Équipes avec forte activité CI/CD, dépendances nombreuses |
| Mensuelle | Projets stables, outillage peu changeant |
| À la demande | CVE critique dans une dépendance détectée par la veille |
Cas pratique 6 — Onboarding express
Section intitulée « Cas pratique 6 — Onboarding express »Un nouveau DevOps rejoint l’équipe. En moins de 15 minutes, il dispose de l’environnement complet.
-
Installer Nix (une seule fois, 3-5 minutes)
Fenêtre de terminal sh <(curl -L https://nixos.org/nix/install) --no-daemonsource ~/.nix-profile/etc/profile.d/nix.sh -
Activer les flakes
Fenêtre de terminal mkdir -p ~/.config/nixecho "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf -
Cloner et entrer dans l’environnement
Fenêtre de terminal git clone https://gitlab.mon-org.example.com/infra/devops-tools.gitcd devops-toolsnix develop -
Vérifier
Fenêtre de terminal terraform versionkubectl version --clienthelm versionansible --versionToutes les versions affichées sont identiques à celles du reste de l’équipe.
-
(Optionnel) Activation automatique avec direnv
Fenêtre de terminal nix profile install nixpkgs#direnvecho 'eval "$(direnv hook bash)"' >> ~/.bashrcsource ~/.bashrcdirenv allow .À partir de là,
nix developse déclenche automatiquement à chaquecddans le répertoire.
Le README d’installation se réduit à ces 5 étapes. Plus de liste de paquets à maintenir, plus de “ça marche chez moi”.
Fil rouge : projet Python + Terraform + Ansible
Section intitulée « Fil rouge : projet Python + Terraform + Ansible »Voici comment les six cas pratiques se combinent dans un projet réaliste.
{ description = "Infra — Python + Terraform + Ansible";
inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; flake-utils.url = "github:numtide/flake-utils"; };
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; src = ./.; in { # Cas pratique 1 — plusieurs shells selon le rôle devShells = { default = pkgs.mkShell { name = "infra-full"; packages = with pkgs; [ python312 python312Packages.boto3 terraform ansible ansible-lint kubectl helm shellcheck shfmt ]; shellHook = '' echo "Environnement complet actif" ''; }; ci = pkgs.mkShell { # Shell allégé pour la CI — sans éléments interactifs name = "infra-ci"; packages = with pkgs; [ python312 terraform ansible kubectl shellcheck ]; }; };
# Cas pratique 3 — checks automatisés checks = { shellcheck = pkgs.runCommandLocal "check-shellcheck" { buildInputs = [ pkgs.shellcheck ]; } '' find ${src}/scripts -name "*.sh" -exec shellcheck {} + touch $out ''; nixfmt = pkgs.runCommandLocal "check-nixfmt" { buildInputs = [ pkgs.nixfmt-rfc-style ]; } '' nixfmt --check ${src}/flake.nix touch $out ''; };
# Cas pratique 4 — outil interne empaquetable packages.default = pkgs.writeShellApplication { name = "infra-status"; runtimeInputs = with pkgs; [ kubectl jq python312 ]; text = '' echo "=== Cluster status ===" kubectl get nodes -o json | jq -r '.items[].metadata.name' ''; }; } );}Pipeline CI/CD correspondant :
name: Infra CI
on: [push, pull_request]
jobs: checks: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@v31 with: github_access_token: ${{ secrets.GITHUB_TOKEN }} extra_nix_config: | experimental-features = nix-command flakes - run: nix flake check - run: nix develop .#ci --command terraform -chdir=infra validate - run: nix develop .#ci --command ansible-lint playbooks/ - run: nix build .#infra-statusPièges spécifiques au contexte DevOps
Section intitulée « Pièges spécifiques au contexte DevOps »| Piège | Impact | Correctif |
|---|---|---|
git add oublié avant nix develop | Nix ignore silencieusement les nouveaux fichiers | git add -A systématique avant toute commande Nix |
flake.lock absent du dépôt | Chaque machine ou CI job résout une révision différente | Commiter flake.lock — c’est une fonctionnalité, pas un artefact jetable |
| Cache Nix absent en CI | Premier job lent (5-10 min de téléchargements) | Configurer Cachix ou un runner persistant avec /nix monté |
Trop d’outils dans un seul devShell | Temps d’entrée long, résolution de conflits plus probable | Plusieurs devShells nommés selon le rôle (default, sec, ci) |
shellHook lourd | Ralentit chaque nix develop | Garder le shellHook court, déléguer aux scripts |
Ignorer nix flake check en PR | Erreurs de structure détectées trop tard | Ajouter nix flake check --no-build comme premier job |
Mettre à jour flake.lock sans branche dédiée | Impossible de revenir en arrière proprement | Toujours une branche + PR dédiée pour les mises à jour |
À retenir
Section intitulée « À retenir »- La flake devient le contrat entre le poste de développement, la CI et les collègues — une seule source de vérité pour toute l’équipe
nix develop --command ...en CI consomme exactement le même environnement qu’en local — plus de divergenceflake.lockdoit être versionné dans Git — il garantit que tout le monde et la CI travaillent avec les mêmes révisions- Les checks Nix sont mis en cache : un check déjà réussi ne tourne pas une deuxième fois
writeShellApplicationest le moyen propre d’empaqueter des scripts avec leurs dépendances sans polluer le PATH système- L’onboarding se résume à : installer Nix une fois +
git clone+nix develop - Mettez
flake.lockà jour régulièrement via une PR dédiée — jamais directement sur la branche principale