# ─── netboot proxyDHCP ─────────────────────────────────────────────────── # Runs ALONGSIDE the NEC IX router's DHCP. The router leases IPs; dnsmasq only # answers the PXE/boot half and hands out NO addresses. TFTP + HTTP + the local # menu are all served by the netbootxyz container on this host (192.168.10.127). port=0 # disable dnsmasq's DNS server entirely log-dhcp # verbose boot logging (comment out once stable) log-facility=- # send logs to stderr so `docker logs` shows them interface=br0 # LAN bridge ONLY bind-interfaces # don't bind virbr0/virbr1 (libvirt's dnsmasq owns :67 there) dhcp-range=192.168.10.0,proxy # proxyDHCP on the LAN subnet — assigns no leases # ─── client classification ─────────────────────────────────────────────── dhcp-match=set:ipxe,175 # our 2nd-stage iPXE sets option 175 dhcp-match=set:httpboot,option:vendor-class,HTTPClient # UEFI HTTP Boot firmware dhcp-option=tag:httpboot,60,HTTPClient # echo the vendor class back # architecture (DHCP option 93) → EFI vs legacy BIOS, so stage 2 hands an iPXE # client a binary it can actually execute (a BIOS iPXE cannot run a UEFI .efi). dhcp-match=set:efi,option:client-arch,6 # UEFI ia32 dhcp-match=set:efi,option:client-arch,7 # UEFI x86-64 dhcp-match=set:efi,option:client-arch,9 # UEFI x86-64 (alt) dhcp-match=set:efi,option:client-arch,11 # UEFI arm64 # ─── stage 1: raw firmware (NOT iPXE) → hand it the netboot.xyz binary ──── # proxyDHCP REQUIRES pxe-service (not dhcp-boot) to emit a boot offer. The TFTP # server defaults to this dnsmasq host (192.168.10.127) = the container's TFTP. pxe-prompt="Booting netboot.xyz...",0 # 0s timeout — no keypress pxe-service=tag:!ipxe,x86PC,"netboot.xyz (BIOS)",netboot.xyz.kpxe # NOTE: use the SNPONLY EFI build (SNP/UNDI = firmware NIC driver) instead of the # all-drivers netboot.xyz.efi. iPXE's NATIVE driver hangs on some NICs (Intel I219 # in the NUC froze right after "autoexec.ipxe not found"); snponly reuses the # firmware's own driver and boots reliably. Realtek ThinkCentres work either way. pxe-service=tag:!ipxe,BC_EFI,"netboot.xyz (UEFI)",netboot.xyz-snponly.efi pxe-service=tag:!ipxe,X86-64_EFI,"netboot.xyz (UEFI)",netboot.xyz-snponly.efi # UEFI HTTP Boot firmware → fetch the first-stage .efi over HTTP dhcp-boot=tag:httpboot,tag:!ipxe,http://192.168.10.127:8080/menus/netboot.xyz-snponly.efi # ─── stage 2: our netboot.xyz iPXE re-requests → give it OUR next-server ── # The .efi's embedded bootstrap fetches local-vars.ipxe from ${next-server} (the # REAL DHCP server = the NEC IX router), NOT from ${proxydhcp/next-server}. So the # router's DHCP next-server MUST be set to 192.168.10.127 (see README) — otherwise # local-vars is fetched from the router (no TFTP → fails) and, lacking # use_proxydhcp_settings, the bootstrap prompts for a 'p' keypress / falls back to # the public menu. # # The bootfile MUST be a name the bootstrap recognises (netboot.xyz.efi / .kpxe) so # it reaches its :tftpmenu branch and chains menu.ipxe LOCALLY. A non-binary name # like menu.ipxe skips :tftpmenu and boots the PUBLIC boot.netboot.xyz menu instead. # The server field (192.168.10.127) sets ${proxydhcp/next-server}. # # Split by arch: the netboot.xyz bootstrap only string-matches these names (never # execs them), but an ALREADY-iPXE client (e.g. a firmware iPXE ROM) autoboots the # bootfile, so it must be executable on that arch — .efi for UEFI, .kpxe for BIOS. # Both binaries re-run the bootstrap, which then reaches :tftpmenu → local menu. dhcp-boot=tag:ipxe,tag:efi,netboot.xyz-snponly.efi,,192.168.10.127 dhcp-boot=tag:ipxe,tag:!efi,netboot.xyz.kpxe,,192.168.10.127