This repository has been archived on 2026-07-30. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
nixos/docs/pxe-boot.md
beatzaplenty e92aab617f
Check NixOS configurations / eval-hosts (pull_request) Successful in 10m42s
Rename PXE installer menu entry, add vanilla NixOS minimal netboot entry
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.
2026-07-21 22:45:25 +00:00

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 ipxe package:
    • /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-installer is this flake's own netbootSystem (flake.nix) — the same auto-installer image nix build .#pxe produces. See docs/auto-installer.md.
  • nixos-minimal is netbootMinimalSystem (flake.nix) — nixpkgs' netboot-minimal.nix composed on its own, with none of this flake's auto-installer wiring (no common.nix, no auto-install.sh, no baked host keys or custom users). Same nix build .#pxe-minimal mechanism 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.