There are a lot of HowTos in the web talking about PXE boot and how to configure it. But most of them are applied to a particular Linux/Unix distribution or a particular Thin-Client Boot framework.
The goal of this HowTo is to show which components are needed in an PXE boot environment and how they are related to each other. No particular linux distribution and no particular framework.
After this article you will be able to set up a little PXE boot environment in your private (home)network for backup/recovery purpose or just for fun.
This article is not going to explain how to create a “net-bootable” recovery image. This will be discussed in the next article.
The Preboot execution environment makes use of several network protocols of different layers like IP, UDP and/or TCP, DHCP, TFTP and NFS. The protocols or rather the services which have to be configured are DHCP, TFTP and NFS, since IP, UDP and TCP are provided by the TCP/IP stack implemented in your operating system.
- DHCP: In order to connect to the PXE Boot Server, a client needs an IP address at boot. Since on most BIOS you can’t configure a static IP address, you need a configurable DHCP server.
- TFTP: A TFTP server is needed to store the bootstrap program (network-compatible bootloader, in our case the PXE bootloader), the kernel and the initial ramdisk image or whatever your operating system needs.
- NFS: The only purpose of the NFS Server is to share the root partition or rather the squashfs image which we want to boot over the network.
What happens after you start your PC and the PXE boot routine is started:
- The PXE boot routine starts a DHCP discovery to finally get an IP address from the running DHCP Server
- The PXE boot routine downloads the bootstrap program from the TFTP server. (The location of the bootstrap program is set in a DHCP-option)
- The bootstrap program looks for a bootfile with the boot parameters for the current client.
- If no bootfile is found, the PC skips the PXE boot routine and boots locally according to the boot sequence set in the BIOS. Else it boots according to the boot parameters in the netboot file.
- Kernel and initial ram disk image(initrd.img) are downloaded from the TFTP server and executed.
- The kernel mounts the root partition which is provided by the NFS server. The root partition should be a whole NFS share or an image(squashfs) stored on a NFS share.
Installation of the components
Since the “PXE boot” server has to be a *nix operating system, I will use an Ubuntu installation for this howto. But it doesn’t matter which distribution you choose. Every configuration is applicable to any Linux distribution.
Installing DHCP and TFTP
The most elementary solution is to install a software which is easy to configure and provides both services at once.
Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP server. It is designed to provide DNS and, optionally, DHCP, to a small network. It can serve the names of local machines which are not in the global DNS. The DHCP server integrates with the DNS server and allows machines with DHCP-allocated addresses to appear in the DNS with names configured either in each host or in a central configuration file. Dnsmasq supports static and dynamic DHCP leases and BOOTP/TFTP/PXE for network booting of diskless machines.
sudo apt-get install dnsmasq
sudo apt-get install nfs-kernel-server
Installing the bootstrap program “PXE Linux”
PXELINUX is a SYSLINUX derivative, for booting Linux off a network server, using a network ROM conforming to the Intel PXE (Pre-Execution Environment) specification. PXELinux loads the kernel and the inital ramdisk from the TFTP server.
Download SYSLINUX from here.
Make sure to download a version older than 3.4. Syslinux changed from pxelinux to gpxelinux. there is no big difference but I haven’t tested it with gpxelinux yet.
Create a tftproot directory in your home directory ($HOME)
Unpack SYSLINUX and copy pxelinux.0 to the tftproot directory you’ve created before.
tar xzfv syslinux-x.xx.tar.gz
cp $HOME/syslinux-x.xx/pxelinux.0 $HOME/tftproot/
Read the dnsmasq manpage for a better explanation.
In the global configuration file of the dnsmasq daemon we have to set following options:
This sets the DHCP server to authoritative mode. In this mode it will barge in and take over the lease for any client which broadcasts on the network, whether it has a record of the lease or not. This avoids long timeouts when a machine wakes up on a new network.
Never forward plain names (with a dot or domain part)
You can set your internal domain as you want, in this example it’s set to “home.local”. Queries in this domain are answered from /etc/hosts or DHCP only.
This enables the tftp-server and specifies the tftp-root.
Here is the complete sample configuration file:
#Configurationfile for dnsmasq DHCP and DNS Server
dnsmasq provides special configuration files for a multi VLAN environment, so that you can have different DHCP configurations for different VLANS. In our case, since we are talking about a private home network, we only have one VLAN. We could put following configuration in the main configuration file /etc/dnsmasq.conf, but it’s better if you create a VLAN configuration file in /etc/dnsmasq.d/
Create /etc/dnsmasq.d/vlanXXX.dnsmasq.conf, where XXX is the number.
The most important option we need to set is the location where the bootstrap program (network bootloader) is stored on the TFTP server.
Our bootloader is pxelinux.0, wich you’ve put in the tftp-root directory specified in the tftproot directory ($HOME/tftproot)
Here a sample configuration of VLAN 1.
dhcp-range = vlan1,172.16.1.1,172.16.1.253,255.255.255.0,45m
#DHCP Options for VLAN 1
dhcp-option = net:vlan1,1,255.255.255.0 # netmask
dhcp-option = net:vlan1,2,3600 # GMT+1
dhcp-option = net:vlan1,3,172.16.1.254 # Gateway
dhcp-option = net:vlan1,6,172.16.1.1 # DNS Server (this server’s IP address)
dhcp-option = net:vlan1,15,vlan1.home.local # DNS Domain Name (optional)
dhcp-option = net:vlan1,119,vlan1.seclab.local # DNS Search Suffix (optional)
dhcp-boot = net:vlan1,/pxelinux.0
dhcp-host = 00:0E:0C:A1:E3:B1,net:vlan1,172.16.1.1,server.vlan1.home.local #Server
dhcp-host = 00:50:04:0B:43:FC,net:vlan1,172.16.1.2,client1.vlan1.home.local #Client1
Important: Turn the router’s DHCP server off.
Create a pxelinux.cfg direcotry in the tftproot directory
mkdir -p $HOME/tftproot/pxelinux.cfg
The netboot file name depends on the IP address of the booting machines. PXELINUX will search for its bootconfig file on the server in the following way:
First, it will search for the config file using the hardware type (using its ARP type code) and address, all in lower case hexadecimal with dash separators; for example, for an Ethernet (ARP type 1) with address 88:99:AA:BB:CC:DD it would search for the filename 01-88-99-aa-bb-cc-dd.
Next, it will search for the config file using its own IP address in upper case hexadecimal, e.g. 192.0.2.91 → C000025B. If that file is not found, it will remove one hex digit and try again. Ultimately, it will try looking for a file named default (in lower case). As an example, if the boot file name is /mybootdir/pxelinux.0, the Ethernet MAC address is `88:99:AA:BB:CC:DD` and the IP address 192.0.2.91, it will try following files (in that order):
Note that all file name references are relative to the directory pxelinux.0 lives in. PXELINUX generally requires that file names (including any relative path) are 127 characters or shorter in length.
Create the default boot-parameter file in the pxelinux.cfg directory
The default settings provide only the local boot. So if there isn’t an other config file in the pyelinux.cfg directory the computers will boot from the local hard disk.
Create the boot-parameter file which will be used for the netboot. Let’s call it netboot (what an inventive! ;D)
In order to successfully boot from the network you have to tell PXELINUX where the kernel and the inital ramdisk image are stored. The best and easiest way to do it is using symlinks. Remember: all filename references are relative to the directory pxelinux.0 lives in.
Let’s create the symlinks for the kernel (vmlinuz) and the inital ramdisk image (initrd.img) in the tftproot directory where pxelinux.0 lives in.
ln -s /path/where/your/linux-kernel/is/stored/linux vmlinuz
ln -s /path/where/your/initrd.img/is/stored/initramfs initrd.img
Now we can edit the [..]/pxelinux.cfg/netboot file like this..
APPEND initrd=initrd.img vga=0x317 root=172.16.253.3:/nfs/share/of/the/rootfs rootfstype=nfs rootflags="timeo=25,retrans=10"
The label local will be loaded by default. Local boot is the default setting. Now, if you write within 5 seconds (TIMEOUT 50) netboot the system will boot from the network.
PXELINUX will load vmlinuz (the kernel) relatively where pxelinux.0 lives in. You’ve created a symlink in the same direcotry of pxelinux.0, therefore it’s enough to indicate vmlinuz.
APPEND initrd=initrd.img vga=0x317 root=172.16.253.3:/nfs/share/of/the/rootfs rootfstype=nfs rootflags=”timeo=25,retrans=10″
APPEND specifies the boot options. First of all you declare the initial ramdisk image with initrd=initrd.img (Always relatively to pxelinux.0)
vga=0×317 is optional. It makes the screen look better. Newer kernels(>2.6.29) don’t need it anymore.
root=172.16.253.3:/nfs/share/of/the/rootfs declares the rootfs respectively where the file rootfs.img is stored.
rootfstype=nfs declares the FS type. In our case NFS
rootflags=“timeo=25,retrans=10” are NFS mount options which handle timeout issues.
Strictly speaking, you only need to edit /etc/exports to get NFS to work.
This file contains a list of entries; each entry indicates a exported volume and how it will be exported.
Like it was explained in the PXELINUX installation and configuration chapter you have to export the directory of the root partition or rather the rootfs image which is declared in the [..]/pxelinux.cfg/netboot file as option of boot parameter APPEND (root=:/nfs/share/of/the/rootfs)
Add following line in the NFS Exports configuration file /etc/exports
We allow every host in the 172.16.0.0 network to access the nfs-share. The options:
- ro: The directory is shared read only; the client machine will not be able to write it. This is the default.
- no_root_squash: By default, any file request made by user root on the client machine is treated as if it is made by user nobody on the server. (Exactly which UID the request is mapped to depends on the UID of user “nobody” on the server, not the client.) If no_root_squash is selected, then root on the client machine will have the same level of access to the files on the system as root on the server. Without this option the kernel will not be able to load the squashfs image.
- subtree_check: Verifies if the requested file is in the exported tree. Actually this option is not needed anymore, because now it is the default. Every file request is checked to make sure that the requested file is in an exported subdirectory. If this option is turned off, the only verification is that the file is in an exported filesystem.
- Change the boot chain of your PCs in order to boot from PXE first
- Create a sym-link to the netboot on your server with the HEX notification of your subnet
if your subnet is 172.16.1.0/24, you can create a sym-link AC1001 (172.16.1) pointing to the netboot file in tftproot/pxelinux.cfg/.
ln -s netboot AC1001
Every PC in 172.16.1.0/24 will boot from the network.