Disclaimer: Regardless part 0 is more or less around Raspberry Pi, in this post, I am only implementing a bare-minimum version of PXE, it will only handle single architecture (x64) and either UEFI or BIOS, not a general purpose PXE environment. some of the PXE boot environment mentioned should also work with Raspberry Pi 3B+ or above, here’s the official Raspberry Pi documentation.
We need the following for this rudimentary homelab PXE boot setup:
- A Linux system with command line tools:
wget
,tftp
andnmap
- TFTP server
- DHCP server
- HTTP server to serve ISO files over LAN – optional, but highly recommended. We’ll cover this in part 2.
Even I listed 3 “servers” above, think as 3 services, it could be provided by any number of servers, you could have your Linux do TFTP and HTTP, and your router for DHCP, or any other combination.
TFTP setup
Let’s start with the TFTP server. Huge thanks to Canonical folks, the Ubuntu wiki has the 23.04 netboot tarball, a quick tar -xf
will yield all the files and folder structure we need:
|-amd64
| |-grubx64.efi
| |-grub
| | |-grub.cfg
| |-pxelinux.0
| |-linux
| |-ldlinux.c32
| |-initrd
| |-bootx64.efi
| |-pxelinux.cfg
| | |-default
In the above folder structure, pxelinux.0
is for BIOS clients, while bootx64.efi
is for UEFI clients, keep those filenames in mind, we’ll need those in configuring DHCP server in part 2.
There’s plenty TFTP server setup articles, Ubuntu, Raspberry Pi, Windows 10, or docker.
Once TFTP is ready, let’s use the following command to test TFTP, (replace the IP address to your TFTP server)
tftp 10.1.2.3
Then:
tftp> get grubx64.efi
If you see File not found error, that means your TFTP path is incorrectly configured.
tftp> get grubx64.efi
Error code 1: File not found
You should see something like this:
tftp> get grubx64.efi
Received 2302218 bytes in 0.7 seconds
Also try files in a folder:
tftp> get grub/grub.cfg
Received 943 bytes in 0.0 seconds
TFTP requires no login credential, I also found mixed results if the default tftp config allows file upload, it probably needs to be secured in some way, but I digress. Once it’s verified operational, take notes of your TFTP Server IP address.
DHCP setup
Next is the DHCP server. In short, we need option 66 for the TFTP server, and option 67 for the boot image filename. DHCP relay (aka IP helpers) or not, some DHCP server somewhere is gonna give you the TFTP server IP and the NBP (Network Boot Program) path.
The easiest method is to check your router, in a home network environment, most likely your router is already doing the DHCP work. If you have a unwieldy router that lacks the configuration, there’s a few routes (pun intended):
- Setup your own DHCP server (and disable the DHCP server in the router)
- Reflash the router firmware to OpenWRT and follow the PXEBoot instructions.
- Get a proper router, such as OPNSense box, UniFi ecosystem, or something else.
First option, the most popular choices are isc-dhcp-server
, or dnsmasq
. No matter which you choose, it only works if it’s the only DHCP server in your network (i.e. you need to turn off the DHCP in your router). In the unfortunate event that your all-in-one box (modem + router + wifi) is supplied by your ISP and not configurable, you’ll need a separate router (and subnet) behind it. Worst case is to double-NAT the devices you intend to PXE boot. Otherwise, bridge mode, or IP passthrough might be possible, YMMV.
Second & third option would be best for existing modem + router/wifi setup – as there are separate devices. There’s more options as it involves how you want to setup your home network / homelab, it’s a deep rabbit hole and probably warrants a series of articles, but I digress…
Here’s the configuration in my UniFi router.
Once done configuring DHCP, use the following command to test:
sudo nmap --script broadcast-dhcp-discover
You should see the following output:
Starting Nmap 7.80 ( https://nmap.org ) at 2023-10-11 23:13 PDT
Pre-scan script results:
| broadcast-dhcp-discover
| Response 1 of 1:
| IP Offered: 10.1.0.12
| DHCP Message Type: DHCPOFFER
| Server Identifier: 10.1.0.1
| IP Address Lease Time: 2m00s
| Bootfile Name: bootx64.efi\x00
| Renewal Time Value: 1m00s
| Rebinding Time Value: 1m45s
| Subnet Mask: 255.255.0.0
| Domain Name: local
| Broadcast Address: 10.0.255.255
| TFTP Server Name: 10.1.2.3\x00
| Domain Name Server: 10.2.1.99, 10.2.1.98
|_ Router: 10.1.0.1
You might notice the \x00
at the end of TFTP server name and Bootfile Name, it is normal:
…the receiver of such options MUST be prepared to delete trailing nulls if they exist.
RFC 2132
In part 2, we’re gonna test PXE boot, and customize GRUB to our liking.