Naar de inhoud

Blog ·

Van DHCP-antwoord naar afgeronde installatie

Netboot deel twee. Wat er na het aanbod gebeurt: het bootscript, het antwoordbestand, de terugmelding die niemand schrijft, en wie een checksum publiceert.

Door Provibr

Een machine zover krijgen dat hij een netbootaanbod aanneemt is het deel waar iedereen over schrijft. Wij schreven er ook over, nadat we een week kwijt waren aan het bestemmingsadres van een proxy-DHCP-antwoord.

Het deel daarna krijgt bijna geen aandacht, en daar zitten de werkelijke storingen. Een machine die opstart en daarna eeuwig op een vraag blijft staan is erger dan een machine die nooit opstartte, want het ziet eruit als voortgang. Dit is de tweede helft: wat er waar moet zijn tussen het binnenkomen van het aanbod en het verschijnen van een inlogprompt, en welke van die dingen stil falen.

De vijf dingen die geserveerd worden

Zodra de client een aanbod en een bootbestand heeft, is een onbewaakte installatie vijf artefacten. Geen van de vijf is optioneel, en het laatste is het artefact dat mensen weglaten.

#WatGeserveerd doorHoe het faalt
1BootscriptHTTPMachine valt terug op een shell
2KernelHTTPBoot breekt af
3InitrdHTTPBoot breekt af
4AntwoordbestandHTTPInstallatieprogramma stelt een vraag en wacht
5Terugmelding bij afrondingHet geïnstalleerde systeemAlles hangt tot er een deadline verstrijkt

De interessante kolom is de laatste. Onderdeel 1 tot en met 3 falen luidruchtig, op het scherm, op een manier die iemand opmerkt. Onderdeel 4 en 5 falen als een installatie die lijkt te draaien en nooit klaar is.

Bootscripts en het plaatshouderprobleem

Het bootscript moet absolute URL's noemen, en het kan ze niet kennen op het moment dat het profiel geschreven wordt: het adres van wat die bestanden serveert hangt af van het segment waarop de machine opkwam.

Het profiel bevat daarom een plaatshouder die bij het serveren vervangen wordt. De onze is @@PROVIBR_BASE@@, en die vorm is een bewuste keuze en geen stijlvoorkeur.

De voor de hand liggende vorm zou ${BASE} zijn. Dat is precies verkeerd, want iPXE vult ${...} zelf in. Een vervanging die niet plaatsvindt wordt dan een lege string in plaats van een fout, en je zit te staren naar

text
chain http:///vmlinuz

met de vraag wat er mis is met je webserver. Een scheidingsteken dat de bootloader niet herkent maakt van een stille mislukte vervanging een zichtbare.

De drie kernelcommandoregels die ertoe doen, als je de merknamen weglaat:

text
# Ubuntu (subiquity)
kernel <kernel> initrd=<initrd> ip=dhcp autoinstall ds=nocloud;s=<dir>/ --- || goto failed

# Debian (preseed)
kernel <kernel> initrd=<initrd> auto=true priority=critical ip=dhcp url=<file> DEBIAN_FRONTEND=text --- quiet || goto failed

# RHEL family (Anaconda)
kernel <kernel> initrd=<initrd> ip=dhcp inst.repo=<tree> inst.ks=<file> inst.text || goto failed

Drie installatieprogramma's, drie volledig verschillende woordenschatten voor hetzelfde idee, en het argument dat het antwoordbestand draagt wordt in elk ervan anders geschreven. ds= neemt een map; url= en inst.ks= nemen een bestand. Haal je dat door elkaar, dan krijg je een installatieprogramma dat opstart en daarna de eerste vraag stelt.

De vier autoinstall-sleutels die bepalen of hij klaarkomt

Ubuntu's autoinstall verdient een eigen alinea, want op een geïsoleerd segment scheiden vier sleutels een installatie die afrondt van een die dat niet doet, en geen ervan gaat over schijven of gebruikers:

  • interactive-sections: []: zonder deze stopt subiquity alsnog om iets te vragen.
  • refresh-installer.update: false: zonder deze gaat hij eerst op zoek naar een nieuwer installatieprogramma.
  • apt.fallback: offline-install: zonder deze wacht hij op het archief voordat hij opgeeft.
  • drivers.install: false: dezelfde soort probleem, dezelfde afloop.

De storing is in alle gevallen dezelfde: een scherm dat er bezig uitziet. Er is geen foutmelding, want vanuit het gezichtspunt van het installatieprogramma is er niets misgegaan.

Er is een bijpassende vlag voor het medium. De netboot-initrd van Ubuntu pakt een installatiemedium uit in een tmpfs en installeert daaruit; vertel je hem niet waar dat medium staat, dan gaat hij het op het internet zoeken. Op een segment zonder uplink is dat het verschil tussen werken en vier minuten niets, gevolgd door een busybox-prompt.

De terugmelding die niemand schrijft

Onderdeel 5 op de lijst is één regel in een post-installatiescript die een URL ophaalt, en het is het meest gemiste stuk in een zelfgebouwde opzet.

Zonder die regel is er geen gebeurtenis die klaar betekent. Het installatieprogramma start opnieuw op, de machine komt op, en het systeem dat de installatie startte weet van niets, dus wacht het tot welke deadline het ook heeft en meldt daarna een timeout op een machine die perfect geïnstalleerd is.

Twee details maken dit minder vervelend dan het klinkt. Ten eerste: lever de hook in het sjabloon in plaats van hem te documenteren, zodat iemand die zijn eigen post-installatiescript schrijft niet hoeft te weten dat hij bestaat. Ten tweede: zorg naast een hook voor succes ook voor een hook voor mislukking. Een installatie die om 04:00 mislukt en dat zegt, is een andere supportervaring dan een die stil valt.

En houd twee klokken aan, niet één. Het commando dat een installatie start hoort klaar te zijn zodra de luisteraars draaien en de sessie is aangenomen, niet als de installatie klaar is; het onze heeft daar een deadline van 90 seconden voor, tegenover een installatiebudget van een uur dat aan beide kanten wordt afgedwongen. Eén deadline voor allebei levert of een taak op die een uur in de interface staat zonder iets te doen, of een installatie die wordt afgebroken omdat hij zo lang duurt als installaties duren.

Welke leveranciers een checksum publiceren, gemeten

Haalt de machine een kernel en een initrd over HTTP van een mirror, dan hoort iets te verifiëren wat er terugkwam. De manier om dat te doen is een sha256 in het profiel vastpinnen en die na het downloaden controleren, op de plek die het ophalen doet.

Dat werkt alleen als de leverancier er een publiceert. Wij namen aan dat het antwoord "meestal niet" was, schreven dat op, en het bleek in drie van de vier gevallen fout. Wat er werkelijk gepubliceerd wordt, gemeten op 2026-09-02:

LeverancierNetboot-kernel + initrdWaar
DebianJaSHA256SUMS naast installer-amd64/current/images/
RHEL-familieJa[checksums] in de .treeinfo naast de tree
Ubuntu (live server-ISO)JaSHA256SUMS naast de release
Ubuntu (netboot-kernel + initrd)NeeGeen checksumbestand in de netbootmap, en de tarball staat ook niet in de releasesommen

De prijs van die verkeerde aanname was geen storing; hij was op een stille manier erger. Assets die vastgepind hadden kunnen worden stonden als niet-verifieerbaar gemarkeerd, en profielen meldden zichzelf als niet installeerbaar terwijl de leverancier het antwoord in het volle zicht publiceerde. Vier van de vijf artefacten over de eerste twee profielen.

Het gedrag als er werkelijk geen checksum bestaat is het waard om bewust te ontwerpen. Bij ons blijft de pin leeg, wordt het asset als wachtend gemarkeerd, en meldt het profiel zichzelf als niet installeerbaar tot een beheerder er een hash in plakt. Dat is met opzet luider dan het toch maar downloaden. Een niet-geverifieerde kernel die over HTTP van een mirror wordt gehaald is de meest waardevolle plek om een provisioningsysteem aan te vallen, en "we konden dit niet verifiëren dus deden we het toch" is geen beleid.

Wat "onderhouden" mag betekenen

We leveren tien basisprofielen: Ubuntu Server 24.04 en 26.04, Debian 12 en 13, Rocky Linux 9 en 10, AlmaLinux 9 en 10, CentOS Stream 10, Fedora Server 44.

De ondersteuningsstatus die eraan hangt wordt berekend, niet ingetypt. Een profiel mag zichzelf alleen onderhouden noemen als het een geverifieerde run heeft op beide firmwarepaden, BIOS en UEFI. Eén van de twee geeft "preview". Geen van beide geeft "niet onderhouden".

Daar een regel van maken in plaats van een veld is dat beetje code waard. Een met de hand ingetypt label is precies zoveel waard als de zorgvuldigheid van degene die het typte, en dit is een label op grond waarvan een klant een machine neerzet.

Dat betekent dat we duidelijk moeten zijn over waar we vandaag staan. Ubuntu Server 26.04 en Debian 13 hebben zichzelf volledig onbewaakt geïnstalleerd op een geïsoleerd segment, op een BIOS-machine. Het UEFI-pad is in dezelfde ronde gerepareerd, en repareren is niet hetzelfde als draaien. Geen enkel standaardprofiel is op het moment van schrijven dus maintained, en de profielen uit de RHEL-familie hebben helemaal niet op een echte machine gedraaid: ze zijn geschreven uit de documentatie van de leverancier en gemeten tegen echte bronbestanden, wat een zwakkere bewering is dan het van buitenaf lijkt.

Los daarvan staat netboot aanbieden als manier om een nieuwe machine te maken standaard uit in ons platform, in afwachting van precies één ding: een echte machine die zichzelf op die manier installeert, op echte firmware. Het pad dat wel bestaat en gebruikt wordt is herinstallatie over een bestaande machine heen. Een functievlag die aanstaat omdat de code geschreven is, in plaats van omdat het ding werkend is waargenomen, levert een bestelknop op die bij de eerste echte klant halverwege strandt.

Kleine dingen die elk een middag kosten

  • Valideer de paden van geserveerde bestanden. Geen leidende slash, geen .., geen backslashes, één tekenklasse. Het ding dat bestanden serveert staat binnen iemands netwerk met een bestandssysteem erachter.
  • Schoon de auditrij. Leg vast welk bestand geserveerd werd en of het een geheim droeg, nooit de inhoud. Wie de inhoud nodig heeft kan het profiel opnieuw renderen.
  • Laat het antwoordbestand geen tweede bron van waarheid zijn over het medium. Het kernelargument en het antwoordbestand noemen allebei waar de pakketten vandaan komen; ze allebei uit één instelling afleiden is de enige manier waarop ze gelijk blijven.
  • Ga ervan uit dat niemand naar de console kijkt. Elke keuze hierboven is een keuze over wat er gebeurt als de installatie op minuut zes van acht is en er niemand in de kamer is.

Dit is het tweede deel van het stuk over waarom UEFI-netboot faalt waar BIOS het wel doet, en het kwam voort uit het bouwen van netwerkinstallatie in Provibr. De details staan in de netbootdocumentatie.

Begin met één host en één agent

Maak een account aan, installeer de agent met één commando en koppel je eerste Proxmox-host. De proefperiode loopt 14 dagen en vraagt geen betaalgegevens.