How to run your own ad-hoc PXE boot server

Note: This is part of the documentation how to build your own bootable CD. a bootable USB stick, or a PXE boot server. If you came here by accident, please read that page first.

An ad-hoc PXE boot server

As I explained in the main doccument, the ability to run a PXE boot server is an important tool in your toolbox. Running a PXEboot server is relatively straightforward to set up if you control both the dhcp and a tftp server on your network. This is very often not the case. If not, this becomes a bit more involved. However, you can turn your laptop or another dedicated machine into a standalone boot server with a bit of effort. Let me explain.

I sidestep all the complications of running a PXE environment on the general network by making a point-to-point network connection between my laptop and the machine to be booted, and set up my laptop as the boot server. My laptop is typically connected on the wireless network at work, which means that the wired ethernet port (or, if you don't have one, a USB-Ethernet adapter) is available for the point-to-point connection. That means:

In particular the first point is important. You should make double sure that you are not conflicting with your organization's dhcp server. If you do, you might be losing friends really fast.

How this is accomplished varies from distribution to distribution, so check the documentation. As an example, here is how it is done on my laptop running Gentoo.

In /etc/conf.d/dhcpd there is a section

# Configure which interface or interfaces to for dhcpd to listen on.
# List all interfaces space separated. If this is not specified then
# we listen on all interfaces.
DHCPD_IFACE="eth0"

I then bring up my eth0 interface with a private address (I arbitrarily chose 192.168.80.1) and configure the DHCP server to hand out addresses 192.168.80.100 to 192.168.80.254 (which is overkill, since we need only one address). Here is my dhcpd.conf file. Note the "filename" and "next-server" options, which specify the boot file and where to get it from:

 
# cat /etc/dhcp/dhcpd.conf

subnet 192.168.80.0 netmask 255.255.255.0 {
        range 192.168.80.100 192.168.80.254;
        default-lease-time 3600;
        max-lease-time 4800;
        option subnet-mask 255.255.255.0;
        filename "PXE/pxelinux.0";
        next-server 192.168.80.1;

I configure my tftp server to only listen on that eth0 interface. Here is the configuration for my laptop (again, highly distribution-specific):

$ cat /etc/conf.d/in.tftpd 

# Path to serve files from
INTFTPD_PATH="/tftpboot/"

INTFTPD_OPTS=" -4 --address 192.168.80.1 -l -v -R 4096:32767 -s ${INTFTPD_PATH}"

This makes the tftp server listen only on the IPv4 address given, started in standalone mode (not under xinetd control), with the specified port range. This is good enough for our server which needs to be up only as long as the other machine takes to boot.

So if a host is set up to boot through PXE, it will obtain an address, and load the "PXE/pxelinux.0" file from the "next server" 192.168.80.1 (that's us). All of the following is relative to our tftp area, which is, by default, /tftpboot, and then relative to the location of the pxelinux.0 file, that is, relative to that "PXE" directory.

In there, we find

$ ls -l  /tftpboot/PXE
total 96828
-rw-r--r-- 1 root root      787 Mar 31 19:58 boot.msg
-rw-r--r-- 1 root root    26579 Mar 31 19:58 pxelinux.0
drwxr-xr-x 2 root root        8 Mar 31 19:58 pxelinux.cfg
-rw-r--r-- 1 root root 49646485 Mar 31 19:58 sdisk32.img
-rw-r--r-- 1 root root 44860071 Mar 31 19:58 sdisk64.img
-rw-r--r-- 1 root root  2234240 Mar 31 19:58 vm32
-rw-r--r-- 1 root root  2370656 Mar 31 19:58 vm64

pxelinux.0 is the PXE bootloader, and pxelinux.cfg is the configuration directory. You can use this to tailor exactly which machines can use our PXE boot mechanism, but since there is only one in our case, we just have a "default" configuration file, which poses no restrictions. It is a straight copy of the isolinux.cfg file which governs the boot from the CD.

Since in most cases your tftp server will be different from the machine on which you build the boot images, the "PXE" target (make PXE) will give you a tftp_area.tar.gz tarball, which you can transfer to your server and unpack in your tftp area. It will give you the exact directory structure as shown above.

In order to streamline setting up the boot server on demand, I have made a simple script setup_pxe_boot.sh, which is highly distribution-specific, but might help you devise a similar setup. Just executing the script by itself starts the services, and calling it with any parameter, such as "stop", will stop them again. Along the way, I set the private 192.168.80.0 network up to be masqueraded, so the booting machine has a chance to reach out to the general internet. (In the dhcpd configuration file I make no attempt to communicate a name server to the booted machine; in the few cases where I need this, I can set it by hand).

#! /bin/sh 

if [ -z $1 ] ; then

    echo "starting network..."
    ifconfig eth0 192.168.80.1 up

    echo "starting tftp..."
    /etc/init.d/in.tftpd start

    echo "starting dhcpd..."
    /etc/init.d/dhcpd  start

    iptables -I INPUT -s 192.168.80.0/24 -j ACCEPT
    iptables -t nat -A POSTROUTING -o wlan0  -j MASQUERADE
    echo 1 >   /proc/sys/net/ipv4/ip_forward 

    exit
fi

echo "stopping tftp..."
/etc/init.d/in.tftpd stop

echo "stopping dhcpd..."
/etc/init.d/dhcpd  stop

echo "stopping network..."
ifconfig eth0 down

iptables -D INPUT -s 192.168.80.0/24 -j ACCEPT
iptables -t nat -D POSTROUTING -o wlan0  -j MASQUERADE
echo 0 >   /proc/sys/net/ipv4/ip_forward 

Enjoy!