PXE (Preboot Execution Environment) lets a machine boot over the network with no physical install media: firmware requests a DHCP lease, gets pointed at a TFTP server, downloads a small bootloader, and that bootloader fetches a kernel/initrd (and, for Kickstart/Autoinstall/Preseed, the answer file) over TFTP or HTTP. It is the delivery mechanism the other pages in this section usually assume once you move past a single one-off VM.
What's required¶
- DHCP that hands out
next-server(the TFTP server IP) andfilename(the bootloader path) alongside the normal lease, or a separate DHCP proxy if you can't touch the main DHCP server's config - TFTP serving the bootloader and kernel/initrd
- HTTP (usually) serving the actual kickstart/preseed/autoinstall file and the install tree, since TFTP is slow and stateless for anything beyond the initial small files
A minimal all-in-one server with dnsmasq¶
dnsmasq can act as DHCP-proxy (not replacing an existing DHCP server) plus TFTP plus a small HTTP helper, which is the easiest way to stand up netboot without touching a production DHCP server's config:
# /etc/dnsmasq.d/pxe.conf
interface=eth0
dhcp-range=192.0.2.0,proxy # proxy mode: piggybacks on existing DHCP, only adds boot info
dhcp-boot=pxelinux.0
enable-tftp
tftp-root=/srv/tftp
# For UEFI clients, serve a different bootloader based on the client arch (option 93)
dhcp-match=set:efi-x86_64,option:client-arch,7
dhcp-boot=tag:efi-x86_64,bootx64.efi
mkdir -p /srv/tftp/pxelinux.cfg
cp /usr/lib/syslinux/pxelinux.0 /srv/tftp/
cp /usr/lib/syslinux/modules/bios/{ldlinux,libcom32,libutil,menu,vesamenu}.c32 /srv/tftp/
# /srv/tftp/pxelinux.cfg/default
DEFAULT rhel9
LABEL rhel9
KERNEL rhel9/vmlinuz
APPEND initrd=rhel9/initrd.img inst.ks=http://<server>/kickstart/server01.cfg ip=dhcp
LABEL ubuntu-autoinstall
KERNEL ubuntu/vmlinuz
APPEND initrd=ubuntu/initrd autoinstall ds=nocloud-net;s=http://<server>/autoinstall/
Copy the distro's vmlinuz/initrd.img from the install ISO into matching subdirectories under /srv/tftp/, and serve kickstart/, autoinstall/, or preseed.cfg over a plain web server (nginx/Apache, or even python3 -m http.server for quick testing).
iPXE for HTTP-chainloading and flexibility¶
iPXE replaces the legacy PXE ROM/pxelinux.0 chain with a scriptable bootloader that can itself fetch its next stage over HTTP (faster and easier to firewall than raw TFTP), and supports conditionals — e.g. choosing an image by MAC address:
#!ipxe
:menu
menu Choose an OS
item rhel9 RHEL 9 (Kickstart)
item ubuntu Ubuntu Server (Autoinstall)
choose target && goto ${target}
:rhel9
kernel http://<server>/rhel9/vmlinuz inst.ks=http://<server>/kickstart/server01.cfg ip=dhcp
initrd http://<server>/rhel9/initrd.img
boot
:ubuntu
kernel http://<server>/ubuntu/vmlinuz autoinstall ds=nocloud-net;s=http://<server>/autoinstall/
initrd http://<server>/ubuntu/initrd
boot
Point dhcp-boot at ipxe.efi/undionly.kpxe instead of pxelinux.0/bootx64.efi to chainload into this instead.
netboot.xyz¶
netboot.xyz is a ready-made iPXE menu server covering most common distros' installers, useful for a lab/homelab where maintaining your own kernel/initrd mirror for every distro isn't worth it — point dhcp-boot at their hosted (or self-hosted, via their Docker image) boot menu and it handles the rest, though for anything beyond a stock install you'll still supply your own kickstart/autoinstall/preseed URL as a kernel parameter as shown above.
Where Cobbler/Foreman fit in¶
Cobbler and Foreman automate everything on this page — DHCP reservations, TFTP file layout, PXE menu generation, per-host kickstart/preseed rendering — behind a CLI/web UI, so you stop hand-editing pxelinux.cfg entries and dnsmasq.conf for every new host or distro version. Worth adopting once you're maintaining netboot for more than a handful of machines by hand.