The iPXE menu's "nixos" entry actually chain-loads this flake's own custom auto-installer image, not a stock NixOS image — rename it to "auto-installer" (label "NixOS Auto-Installer") so the menu says what it boots, and set networking.hostName on netbootSystem to match, so the generated system name (nixos-system-auto-installer-*) and staged directory (/srv/pxe/http/auto-installer) agree with the menu entry too. Add a second, genuinely vanilla NixOS minimal netboot image (netbootMinimalSystem in flake.nix — nixpkgs' netboot-minimal.nix on its own, none of modules/installer/common.nix's auto-installer wiring), built from source the same way as the auto-installer image and exposed as packages.x86_64-linux.pxe-minimal. Staged and menu-wired the same way, as "nixos-minimal" (item, hostname, and directory all matching). modules/pxe-boot/stage-installer-artifacts.nix is generalized to stage both images via a shared rule-builder instead of one hardcoded set of paths. Verified: nix eval confirms both images' config.system.name matches their menu entry/directory names, the pxe-boot host itself builds clean with the new menu.ipxe, and the new pxe-minimal image was booted directly under QEMU (kernel+initrd, no KVM) to a working login shell with hostname nixos-minimal, no hang.
4.2 KiB
pxe-boot
The pxe-boot host serves HTTP boot assets for iPXE clients — including
self-staged copies of both this flake's own auto-installer netboot image
(see docs/auto-installer.md for what that image actually is and does once
booted) and a vanilla, unmodified NixOS minimal netboot image for plain
rescue/inspection use.
Host Role
- Hostname:
pxe-boot - Web service: nginx on TCP port 80
- PXE root:
/srv/pxe - HTTP root for scripts and images:
/srv/pxe/http - TFTP root for first-stage bootloaders:
/srv/pxe/tftp - iPXE entry script:
/srv/pxe/http/boot.ipxe - Generated iPXE menu:
/srv/pxe/http/menu.ipxe - SystemRescue iPXE script:
/srv/pxe/http/systemrescue.ipxe - TFTP fallback script:
/srv/pxe/tftp/autoexec.ipxe - Boot binaries copied from the Nix
ipxepackage:/srv/pxe/tftp/ipxe.efi/srv/pxe/tftp/undionly.kpxe
Directory Layout
The host creates these directories with systemd tmpfiles:
/srv/pxe
/srv/pxe/http
/srv/pxe/http/images
/srv/pxe/http/auto-installer
/srv/pxe/http/nixos-minimal
/srv/pxe/http/systemrescue
/srv/pxe/http/ubuntu
/srv/pxe/http/rescue
/srv/pxe/tftp
Mount shared image storage under /srv/pxe/http, preferably
/srv/pxe/http/images unless a menu entry expects files in a specific
directory such as /srv/pxe/http/auto-installer.
The HTTP iPXE chain is:
undionly.kpxe or ipxe.efi
-> autoexec.ipxe from the TFTP root, when iPXE requests it
-> http://192.168.2.247/boot.ipxe
-> http://192.168.2.247/menu.ipxe
The generated menu currently exposes entries for:
- NixOS Auto-Installer
- NixOS Minimal
- SystemRescue environment
- iPXE shell
- Reboot
Both NixOS entries chain-load a netboot.ipxe staged into their own
directory (/srv/pxe/http/auto-installer/netboot.ipxe and
/srv/pxe/http/nixos-minimal/netboot.ipxe), each nixpkgs' own generated
netboot iPXE script (correct init=/initrd= kernel parameters included)
rather than a hand-rolled boot line — that script in turn expects its
kernel/initrd siblings in the same directory. Each directory's three files
(bzImage, initrd, netboot.ipxe) are built from source and staged
automatically by modules/pxe-boot/stage-installer-artifacts.nix via
systemd.tmpfiles.rules — no manual operator step required:
auto-installeris this flake's ownnetbootSystem(flake.nix) — the same auto-installer imagenix build .#pxeproduces. Seedocs/auto-installer.md.nixos-minimalisnetbootMinimalSystem(flake.nix) — nixpkgs'netboot-minimal.nixcomposed on its own, with none of this flake's auto-installer wiring (nocommon.nix, noauto-install.sh, no baked host keys or custom users). Samenix build .#pxe-minimalmechanism as the auto-installer image, just a different module composition. Useful as a plain rescue/inspection shell that doesn't assume anything about this flake.
Both images set networking.hostName to match their menu entry/staged
directory name (auto-installer / nixos-minimal), so each one's
generated system name (nixos-system-<name>-*) is self-describing rather
than the nixpkgs default of nixos-system-nixos-* for both.
The SystemRescue entry expects the source ISO at:
/srv/pxe/http/images/systemrescue.iso
The stage-systemrescue.service oneshot extracts that ISO into:
/srv/pxe/http/systemrescue
The rescue menu entry then chains http://192.168.2.247/systemrescue.ipxe,
which loads the SystemRescue kernel and initramfs from the extracted tree and
uses archiso_http_srv to fetch the squashfs payload over HTTP.
Validation
Safe evaluation check:
nix eval .#nixosConfigurations.proxmox-pxe-boot.config.system.build.toplevel.drvPath --raw
After deployment by an operator, basic service checks are:
curl http://pxe-boot/boot.ipxe
curl http://pxe-boot/menu.ipxe
curl http://pxe-boot/systemrescue.ipxe
curl -I http://pxe-boot/systemrescue/sysresccd/boot/x86_64/vmlinuz
curl -I http://pxe-boot/systemrescue/sysresccd/boot/x86_64/sysresccd.img
During a successful BIOS chainload, TFTP should deliver undionly.kpxe once,
then nginx should log requests for /boot.ipxe and /menu.ipxe. Repeated TFTP
downloads of undionly.kpxe indicate the iPXE stage is still not reaching the
HTTP chain.