Update pxe boot flow

This commit is contained in:
Audiobuzz
2026-06-20 09:17:05 +00:00
parent e3978bb210
commit fb69068980
8 changed files with 336 additions and 2 deletions
+46
View File
@@ -48,6 +48,26 @@ services:
# + DNS A/PTR. Auto-populated by fleet-namer (creative names per MAC); add
# manual lines to pin specific hosts. RW so fleet-namer can append.
- ./dnsmasq/dhcp-hosts:/etc/dnsmasq-hosts
# iPXE binary source (read-only) for the PXE-only chainload (firmware without
# UEFI HTTP boot, e.g. EliteBook 820 G4). Drop ipxe.efi here — see
# serving/tftp/README. The entrypoint copies it into /srv/tftp and renders
# boot.ipxe alongside it (the actual TFTP root is container-internal).
- ./tftp:/tftp-src:ro
# The release artifacts (same image volume as the http service), read-only,
# so the entrypoint can objcopy the UKI's .cmdline section into boot.ipxe
# (Secure Boot OFF needs the real cmdline fed to iPXE — see entrypoint.sh).
- type: image
source: ${OCI_IMAGE}:${IMAGE_VERSION}
target: /artifacts
image:
subpath: artifacts
# Fallback (Docker < 28 / offline): bind the local Packer output dir instead:
# - ${ARTIFACT_SRC}:/artifacts:ro
environment:
# Consumed by the entrypoint to render /srv/tftp/boot.ipxe (the iPXE chain
# script that clears load options so the UKI's embedded cmdline survives).
- SERVER_IP=${SERVER_IP}
- IMAGE_VERSION=${IMAGE_VERSION}
command:
- --keep-in-foreground
# Log to stderr so `docker compose logs` captures output. Without this,
@@ -108,6 +128,32 @@ services:
- --dhcp-vendorclass=set:httpboot,HTTPClient
- --dhcp-option=tag:httpboot,60,HTTPClient
- --dhcp-boot=tag:httpboot,http://${SERVER_IP}/fleet-${IMAGE_VERSION}.efi
# ---- PXE -> iPXE -> HTTP chainload (for firmware WITHOUT UEFI HTTP boot) ----
# Graceful fallback: HTTP-capable firmware matches 'httpboot' above and gets
# the UKI directly; PXE-only firmware (PXEClient) gets ipxe.efi over TFTP;
# once iPXE is running it re-DHCPs with user-class "iPXE" and is handed the
# SAME UKI HTTP URL, which it chainloads (.efi -> LoadImage). Each client
# gets the right thing based on what it advertises — no per-host config.
# snponly.efi = UEFI x64 iPXE that rides the FIRMWARE's NIC driver (UEFI SNP)
# instead of iPXE's own — works on virtio VMs AND real hardware where the
# native driver won't bind (e.g. EliteBook 820 G4 / Intel I219-LM, which
# fails ipxe.efi with "No configurable methods"). Ships in Ubuntu's `ipxe`
# package; see serving/tftp/README.md.
# NOTE (lab): the iPXE binary is UNSIGNED, so this path needs Secure Boot OFF.
# For production, sign it with the fleet db key (then SB stays enforced
# end-to-end) — see docs/secure-boot-keys.md.
- --enable-tftp
- --tftp-root=/srv/tftp
- --dhcp-vendorclass=set:pxe,PXEClient
- --dhcp-userclass=set:ipxe,iPXE
# firmware PXE, not yet iPXE -> hand iPXE (UEFI x64) over TFTP
- --dhcp-boot=tag:pxe,tag:!ipxe,snponly.efi
# iPXE running -> hand boot.ipxe (NOT the UKI URL directly). The script
# imgfetch'es the UKI then `imgargs`-clears the load options before boot, so
# systemd-stub uses the UKI's EMBEDDED cmdline. Booting the UKI URL directly
# makes iPXE pass the image name as the cmdline, which (Secure Boot OFF)
# REPLACES the embedded roothash/nvmf/... args -> dracut emergency shell.
- --dhcp-boot=tag:ipxe,boot.ipxe
# --- HTTP boot server (serves the UKI) -------------------------------------
http: