# Bael Serveur DHCP intégré, en coexistence avec dnsmasq, et documentation du projet. ## Fonctionnalités **Serveur DHCP intégré** - Nouveau binaire `dhcp`, une instance par subnet lancée dans le netns du VPC par l'unit `dhcp@_`. Il reçoit son bridge et ses deux chemins de fichiers en paramètres : il ne compose aucun chemin et ignore le netns dans lequel il tourne - Piloté par l'agent sur une **socket Unix** `/run/two/dhcp/_.sock`, en JSON par ligne. Ordres idempotents en remplacement intégral : configuration du subnet à sa création, une réservation par interface à chaque création ou suppression de VM - **Réservations statiques uniquement**, pas de baux : une MAC inconnue n'obtient rien, et le serveur reste silencieux plutôt que de répondre par un refus. Aucun `DHCPNAK` n'est émis - État auto-persisté dans `/run/two/dhcp/_.state`, en écriture atomique et lisible par le seul `root`. Le fichier appartient au processus, qui le relit à son démarrage ; l'agent ne l'écrit jamais et se borne à le supprimer — à la création du subnet pour écarter un résidu, à sa suppression après avoir arrêté l'unit - La route par défaut est décidée **par interface** et non plus par subnet, ce qui permet de ne l'annoncer que sur une interface d'une VM multi-réseaux - L'encodage RFC 3442 de l'option 121 est délégué à `github.com/insomniacslk/dhcp` **Coexistence avec dnsmasq** - Nouvelle clé `dhcp.backend`, `dnsmasq` ou `two`, qui choisit le serveur des subnets **créés par cet agent**. Le défaut est `dnsmasq` : un fichier de configuration de la 0.1.0, non modifié, se comporte exactement comme avant - La bascule est une **opération manuelle** sur un hyperviseur vide — l'option ne migre rien, un subnet déjà créé reste servi par le serveur qui l'a été. La procédure est documentée - Toute valeur autre que `dnsmasq` ou `two` fait échouer le démarrage de l'agent **Exploitation** - Le watchdog interroge le serveur DHCP intégré et compare les réservations servies à celles que la base implique. Il nomme ce qui diverge — ordre perdu à la création, ordre perdu à la suppression, adresse ou route par défaut divergente — et reste en lecture seule - La socket de contrôle répond à `get-state` et à `probe`, ce dernier montrant sans effet de bord ce qui serait envoyé à une MAC donnée : adresse, masque, routeur, DNS et routes - Documentation Sphinx du projet : concepts, architecture, déploiement et exploitation ## Correctifs - **Un fichier de configuration présent mais invalide fait désormais échouer le démarrage.** Jusqu'en 0.1.0 l'erreur de lecture était ignorée : l'agent tournait alors entièrement sur ses valeurs par défaut sans le dire, ce qui rendait indétectable une simple tabulation d'indentation - `probe` annonce explicitement `"served": false` pour une MAC non réservée, au lieu d'omettre le champ et de le rendre indistinguable d'une réponse tronquée ## Changements internes - Le module passe à **Go 1.25**, exigé par la bibliothèque DHCP retenue. La version de Go du workflow de build, restée à 1.21 alors que le module en demandait davantage, est alignée - Nouveau paquet `pkg/db/statefile` : persistance générique d'un état de composant dans un fichier, en écriture atomique. Badger a été écarté pour cet usage — une instance par subnet coûterait une memtable de 64 Mio et quatre goroutines de compaction pour environ un kilo-octet d'état, dans un `tmpfs`, et laisserait un verrou résiduel après un arrêt brutal - `internal/subnet` et `internal/vm` ne parlent plus à dnsmasq en direct mais à une interface `Backend` à deux implémentations ## Périmètre et limites connues Celles de la 0.1.0 restent valables, sauf mention contraire ci-dessus. S'y ajoutent : - **dnsmasq n'est pas retiré** et reste un paquet requis : le backend intégré ne sert que les subnets créés après la bascule, et le retour arrière suppose dnsmasq installé - Pas de DNS, pas de pool dynamique, pas de PXE, pas de DHCPv6 dans le serveur intégré - La comparaison faite par le watchdog porte sur les **réservations** et non sur la configuration du subnet : celle-ci dépend de la route par défaut de l'host, dont la lecture au moment du contrôle produirait de faux écarts. Un serveur dépourvu de configuration est en revanche signalé - L'option 249 (routes classless de Microsoft) n'est pas émise, comme dnsmasq ne l'émet pas - Le serveur intégré écoute UDP/67 sans authentification, comme tout serveur DHCP : l'isolation entre locataires d'un même subnet repose sur les règles ebtables anti-usurpation, inchangées - `internal/dhcpbackend` n'est testé sous Linux que pour ses appels systemd ; le reste, y compris le dialogue avec le serveur intégré, est couvert sur toute plateforme ## Mise à jour depuis la 0.1.0 ```bash curl -O https://git.g3e.fr/syonad/two/raw/branch/main/scripts/deploy.sh bash ./deploy.sh -t 0.2.0 ``` Aucune action n'est requise : sans `dhcp.backend` dans `/etc/two/agent.yml`, le comportement est celui de la 0.1.0. Pour passer au serveur intégré, suivre la procédure de bascule dans la documentation d'exploitation — elle suppose un hyperviseur vidé.