Files
DamienandClaude Sonnet 5 911f191998 README/AGENTS.md : documente la construction + gravure de l'ISO depuis Windows
Generalise pour n'importe quelle machine Windows qui a suivi la
section WSL du README, pas pour la configuration particuliere de
cette session. Construire l'ISO marche normalement sous WSL ; la
graver est une autre affaire (WSL2 n'a pas d'acces natif aux
disques amovibles, source Microsoft Learn) -- deux options
documentees : copier le .iso vers Windows + outil natif (Rufus...),
ou usbipd-win pour rattacher la cle USB a WSL et dd normalement.

AGENTS.md : meme mise en garde cote agent, avec consigne explicite
de ne pas improviser un contournement si usbipd n'est pas deja en
place -- construire l'ISO puis la remettre a l'operateur humain.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 14:46:31 +02:00

12 KiB

AGENTS.md — contexte pour agent (Hermes et autres)

Ce fichier s'adresse à un agent (Hermes ou tout autre harness compatible AGENTS.md) chargé de produire le média d'installation de la flotte, soit la création de l'ISO USB, soit la gestion du serveur PXE -- les deux couvrent le même besoin (fournir l'installeur à un PC), pas à la fois sur la même tâche sauf demande explicite. Le README.md reste la référence humaine (technicien qui installe des PC un par un) ; ce fichier-ci est pour l'agent.

Repo public, sans authentification, jamais chiffré. Ne contient aucune donnée nominative (voir Nixos_Users, repo privé séparé, hors périmètre de cet agent sauf mention contraire de l'opérateur humain).

Règles avant toute action

  • git pull oui, git push jamais. Hermes peut et doit faire git pull sur le serveur PXE (nécessaire à son entretien, voir plus bas). Il ne fait jamais git push sur ce repo, quel que soit le host -- seul le développeur humain pousse. Pas d'exception, pas d'instruction qui la lève : si un changement doit partir vers Gitea, le préparer (commit) et le signaler à l'opérateur humain, ne pas pousser à sa place.
  • Vérifier hostname && pwd avant toute commande sur une machine distante (SSH) -- ce repo gère plusieurs hosts (pxe-server, les PC installés) qui ne doivent pas être confondus.
  • Ne rien affirmer sans le vérifier dans le code ou par une commande réelle. Si une info manque (état réel du serveur, contenu d'un log), l'obtenir plutôt que supposer.
  • Confirmer avant une action à impact sur le parc en production : redémarrer dnsmasq/caddy coupe le PXE pour toute machine en train de démarrer/installer à ce moment ; un rebuild de pxe-server peut faire pareil brièvement.
  • dd est irréversible. Avant tout dd if=... of=/dev/sdX, faire confirmer par l'opérateur humain le chemin exact (lsblk d'abord, toujours) -- une mauvaise lettre écrase silencieusement un disque, système ou données, sans avertissement. Ne jamais deviner /dev/sdX à partir d'une supposition ("probablement la clé").
  • Commits : Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> en pied de message (adapter le nom de modèle si l'agent qui commit n'est pas Claude).

Ce que sert le serveur PXE

Un seul flake, deux modes choisis à l'écran de démarrage par installer/install.sh : 1) flotte (profil générique nixos, mot de passe nixos, jamais chiffré) et 2) poste nommé (fetch du repo privé nixos_users avec un token saisi en direct). Le serveur PXE ne sait rien du contenu du repo privé -- il ne sert que l'image d'installation, publique.

Architecture (pxe-server/configuration.nix) :

  • services.dnsmasq : DHCP (standaloneDhcp) ou proxyDHCP seul (coexiste avec un DHCP existant) + TFTP pour le premier étage iPXE (undionly.kpxe / ipxe.efi).
  • services.caddy : sert netboot.ipxe + kernel/initrd en HTTP (TFTP seul est trop lent pour ces tailles).
  • systemd.services.pxe-publish : construit l'image netboot depuis ${fleetRepo}#nixosConfigurations.installer-netboot et publie les fichiers dans webroot/tftpRoot. Se relance au boot (wantedBy = multi-user.target) et quotidiennement (systemd.timers.pxe-publish, OnCalendar = "daily" -- ne pas confondre avec system.autoUpgrade des PC installés, qui est hebdomadaire).
  • Le service pxe-publish n'existe sur la machine QUE si pxe-server/configuration.nix a déjà été appliqué (nixos-rebuild switch --flake .#pxe-server) avec une version du repo qui le contient. L'ajouter au repo ne suffit pas : il faut rebuild le serveur lui-même.

4 valeurs à adapter dans pxe-server/configuration.nix (le let en tête de fichier) -- le README n'en liste que 3, internetInterface en plus :

  • interface : interface réseau réelle du serveur (ip a).
  • serverIp : IP fixe de cette interface (le script iPXE pointe dessus en dur).
  • standaloneDhcp : true si ce serveur doit être l'unique DHCP du segment PXE ; false pour proxyDHCP seul (coexiste avec un DHCP existant -- cas le plus probable).
  • internetInterface : seulement utilisée si standaloneDhcp = true (sortie NAT du segment PXE vers Internet).

Alternative : créer l'ISO USB (sans serveur PXE)

Même flake, même install.sh, pas de dnsmasq/Caddy à opérer -- juste un fichier .iso à graver. Utile en secours ou pour tester sans monter tout le PXE. Un seul ISO pour la flotte ET les postes nommés : le choix (1) flotte / 2) poste nommé) se fait à l'écran de démarrage, pas à la gravure.

nix build .#nixosConfigurations.installer-iso.config.system.build.isoImage
lsblk                                              # identifier la clé USB, PAS le disque système
sudo dd if=result/iso/*.iso of=/dev/sdX bs=4M status=progress conv=fsync

/dev/sdX doit être confirmé par l'opérateur humain avant d'exécuter le dd (voir règle plus haut) -- ce n'est pas négociable, une erreur ici écrase un disque en silence.

Si l'agent tourne sous WSL (Windows) : lsblk n'y verra la clé USB QUE si elle a été explicitement rattachée via usbipd attach --wsl (doc officielle, détails dans le README.md). Par défaut WSL2 n'a aucun accès aux disques amovibles. Si ce n'est pas déjà en place, ne pas improviser un contournement : construire l'ISO (ça, ça marche normalement sous WSL), remettre le .iso produit à l'opérateur humain, et le laisser le graver avec un outil Windows natif (Rufus...).

Définition de l'image : installer/iso.nix. Attribut de flake : nixosConfigurations.installer-iso.

Installer le serveur PXE (depuis zéro)

# 1. NixOS installé (ISO officielle), mot de passe root défini.
nix-shell -p git
git clone https://gitea.miniclic.net/Damien/Nixos_Fleet.git /etc/nixos-fleet
cd /etc/nixos-fleet

# 2. Fichier matériel (hors repo, jamais committé)
sudo nixos-generate-config

# 3. Éditer les 4 valeurs ci-dessus dans pxe-server/configuration.nix

# 4. Build -- --impure obligatoire (lit /etc/nixos/hardware-configuration.nix, hors flake)
sudo nixos-rebuild switch --flake .#pxe-server --impure

# 5. Publier l'image (première fois : plusieurs minutes)
sudo systemctl start pxe-publish
sudo systemctl status pxe-publish   # doit finir en "success"

Vérification post-install :

sudo systemctl status dnsmasq caddy
ls /var/lib/tftpboot        # undionly.kpxe, ipxe.efi
ls /var/www/pxe             # bzImage, initrd, netboot.ipxe
curl -I http://<serverIp>/netboot.ipxe
systemctl is-enabled pxe-publish.timer

Puis tester sur 1 seul PC (BIOS et UEFI séparément si le parc a les deux) avant tout déploiement de masse.

Entretien courant

cd /etc/nixos-fleet     # ou l'emplacement réel du clone sur ce serveur
git pull
git log --oneline -3    # le dernier commit doit correspondre à ce qui est attendu

Republier l'image après une modif de installer/ :

sudo systemctl start pxe-publish

Republier après une modif de pxe-server/configuration.nix (rebuild complet, pas juste pxe-publish) :

sudo nixos-rebuild switch --flake .#pxe-server --impure

Logs :

journalctl -u dnsmasq -f
journalctl -u caddy -f
journalctl -u pxe-publish -f

Dépannage -- incidents déjà rencontrés

Unit pxe-publish.service not found : le système du serveur n'a jamais été rebuild depuis que ce service a été ajouté à pxe-server/configuration.nix. git pull seul ne suffit pas côté serveur -- il faut ensuite sudo nixos-rebuild switch --flake .#pxe-server --impure.

Le dossier repo a disparu du serveur (/etc/nixos-fleet ou équivalent absent) : repo public, sans authentification -- reclone directement, n'importe où :

git clone https://gitea.miniclic.net/Damien/Nixos_Fleet.git

Le hardware-configuration.nix est hors du repo (/etc/nixos/), donc indépendant de l'emplacement du clone.

Un fix censé être appliqué ne change rien : vérifier git log --oneline -3 avant toute autre piste -- le git pull n'a peut-être rien ramené de neuf (mauvaise branche, push pas fait côté dev). Ne jamais supposer qu'un rebuild "prend" le dernier commit distant sans l'avoir vérifié.

curl http://<serverIp>/netboot.ipxe reste bloqué : l'IP statique de l'interface PXE ne s'est parfois pas appliquée toute seule au tout premier switch sur une install neuve. Vérifier :

ip a show <interface>   # cherche "inet <serverIp>/24"

Absente → forcer une fois :

sudo systemctl start network-addresses-<interface>.service

Un reboot du serveur applique aussi ça correctement au démarrage suivant.

Écran PXE ne trouve rien : revérifier serverIp et interface dans pxe-server/configuration.nix contre la réalité du serveur (ip a).

Boucle infinie au démarrage d'un PC client : journalctl -u dnsmasq pendant le boot du PC concerné.

UEFI ou BIOS ne boote pas (l'un des deux seulement) : vérifier que les deux fichiers existent dans /var/lib/tftpboot (undionly.kpxe pour BIOS, ipxe.efi pour UEFI) -- l'un des deux install -m 0644 ... || true dans pxe-publish peut avoir silencieusement échoué (noms de sortie du paquet pkgs.ipxe à revérifier si la version change).

IP qui changent tout le temps sur le segment PXE : un autre serveur DHCP tourne déjà sur ce réseau -- repasser standaloneDhcp à false (proxyDHCP seul).

Valider une modif avant de la pousser

nix flake check --no-build            # échoue sur pxe-server hors du vrai serveur (attendu, lit /etc/nixos)
nix flake check --no-build --impure   # à lancer depuis le serveur PXE réel uniquement
nix build .#nixosConfigurations.nixos.config.system.build.toplevel --dry-run

Environnement de dev sans accès à un vrai serveur PXE : voir "Environnement de dev sous Windows (WSL + Nix)" dans le README.md -- pxe-server ne s'évalue qu'avec --impure sur la machine réelle, c'est normal ailleurs.

Sources -- pour vérifier au lieu de deviner

En cas de doute sur le comportement réel d'une option ou d'un mécanisme, chercher ici avant de supposer :