So I have a heterogeneous network, and I want to netboot various computers within that network without having to write individual lines in the DHCP server config files. Moreover, the DHCP server for my network lives on a separate router machine with virtually zero disk space, so the PXE server must be separate to that without compromising the rest of the DHCP network. I want to be able to netboot random machines as I quite frequently have computers in the house that need to be wiped and/or reinstalled - ideally this should be as easy and painless as possible. Being able to netboot any machine I plug in to the network will allow for that to be easily done at any time.
Ideally, the PXE server should be able to serve at least the following images to various machines on request:
- Ubuntu Live CD (16.04 & 17.04; i386 & x86_64)
- Windows 7 & 10, Home & Pro; i386 & x86_64
Also, I want to be able to netboot other architectures, specifically Raspberry Pi boards so I don't have to use those pesky SD Cards and can keep them all updated in a single place. In the future I want to also be able to netboot my SGI machine, as the disk in it is old and whines (a bit like me), and also my NextSTEP machine (A HP 712 workstation). If I am successful I may also drag the DEC Alpha out of the garage and sit that on the network too. So any solution I come up with has to be able to accommodate those architectures in the future (without necessarily being used for those more exotic architectures - more on that later). I won't go into the background detail of PXE and netbooting too much as there are plenty of references on the web that explain it a lot better than I'd be able to.
In my preliminary research, I found the following pages which I have found useful in determining the strategy I will take:
- Manski's blog on setting up under Ubuntu
- ubuntu.com PXE Install Howto
- SuSE documentation
- The FOG Project wiki on BIOS vs UEFI net booting
- syslinux wiki page on PXE
I have also taken a lot of inspiration for the menu structure etc from the YUMI Linux usb multiboot installer, from which I have unashamedly copied the menu logo and menu layout (with some modifications).
The server I will use is a machine I have running Ubuntu 17.04. It's a reasonably decent machine, a bit short on RAM with only 4GB but it has enough disk (a pretty-much blank 3TB disk) and a gigabit connection to the main network backplane. In an ideal world I'd rather it be running one of the LTS releases of Ubuntu, but since we will be requiring at least DNSMasq version 2.76 to boot UEFI properly, I've just gone the whole hog and updated to the newest Ubuntu version rather than installing a custom version of DNSMasq (16.04LTS only has v2.75).
For this blog, I'll be following Manski's blog fairly closely, as that's a good starting point that will get us most of the way to where we want to be.
Let's get into it.
First we will ensure we are up to date with all the latest patches etc:
$ sudo apt update ; sudo apt upgrade
Aside: I wanted to put the "and" operator in the command above but the WordPress Markdown plugin I'm using expanded it to "&&" rather than "&&" so I just went with ';'
Install Required Packages
We will need to first of all ensure we have the required packages installed on our Linux server. For this we will initially need dnsmasq, pxelinux and syslinux:
$ sudo apt install dnsmasq pxelinux syslinux-common
We will also require the memtest86 binary as our first netboot target. Luckily I have that kicking about somewhere so don't need to download it, but if you don't have it already you will need to get it from Memtest. On our network (and most networks these days) we already have a working DHCP server, so we will skip any configuration of that and assume that it's all good. For our PXE and TFTPboot server to not tread all over our existing DHCP, we'll have to use the proxy-dhcp mode of DNSMasq; we'll get to that in a minute.
Create Directories for Netboot files
It's here that we will diverge slightly from our primary source (Manski's blog), and create a directory structure for our netboot files based on architecture. This allows us to keep it all a bit more organised, as in the future we may have a whole stack of directories and we don't want to have too many in our tftpboot root. First we will look at our machine to see where we want to put the files we'll serve:
$ df Filesystem 1K-blocks Used Available Use% Mounted on udev 1965796 0 1965796 0% /dev tmpfs 404316 42056 362260 11% /run /dev/sda1 145975872 8001564 130536076 6% / tmpfs 2021576 48 2021528 1% /dev/shm tmpfs 5120 4 5116 1% /run/lock tmpfs 2021576 0 2021576 0% /sys/fs/cgroup /dev/sdb1 2884152988 168921104 2568702224 7% /data tmpfs 404312 148 404164 1% /run/user/1000
We'll chuck our netboot server files into the /data partition - it's a 3TB disk I have preseeded with a whole bunch of IRIX and NextSTEP cd images & boot files for future use, but apart from that is empty. Let's make some of our directories that we'll start with, so we can get an idea of how our system will look when it's fully loaded:
$ mkdir -p /data/tftpboot/i386/memtest \ /data/tftpboot/i386/ubuntu \ /data/tftpboot/x86_64/ubuntu
You can see that gives us plenty of scope for adding new architectures and also new distributions etc without getting too confused about where anything in particular will live. Now we need to create the folder for the menus:
$ mkdir -p /data/tftpboot/pxelinux.cfg
pxelinux.cfg directory we have created must correspond in name to the
pxelinux.0 image we will serve up to our clients. So if a client is served
foo.0, it will need to have a corresponding directory called
foo.cfg. The appropriate bootloader file and corresponding menu file will be served to the requesting device based on the architecture it reports in the PXE request. For this stage we will concentrate on the ubiquitous i386 architecture, and get the memtest86 binary running. In subsequent blogs we will complete the multi-boot menu and multi-arch binary delivery.
Copy Boot Files & Create Our Default Menu
First we need to copy over the memtest86 binary into the appropriate directory. Manski tells us that it's important that the ".bin" suffix is dropped for PXE booting; this is because the
.bin extension is a special meaning extension for a "CD Boot Sector" image, so we drop it on copy:
$ cp /path/to/memtest86+-5.01.bin /data/tftpboot/i386/memtest/memtest86+-5.01
Now we need to put the bootloader and menu file into the root directory of the tftp server, in our case the
/data/tftpboot directory. We'll use a symlink so when our syslinux is updated on the host system it keeps track. Manski tells us to use the ldlinux.c32 file, but we would like a nice menu so we'll use the vesamenu version instead. Note that to use the
vesamenu you will also require the
libutil.c32 files; also we will still need
ldlinux.c32 for all boot modes. At this stage we will copy over a nice menu logo as well; any 640x480 PNG file could be used, we will use a nice image I prepared earlier:
$ ln -s /usr/lib/PXELINUX/pxelinux.0 /data/tftpboot/ $ ln -s /usr/lib/syslinux/modules/bios/vesamenu.c32 /data/tftpboot/ $ ln -s /usr/lib/syslinux/modules/bios/ldlinux.c32 /data/tftpboot/ $ ln -s /usr/lib/syslinux/modules/bios/libcom32.c32 /data/tftpboot/ $ ln -s /usr/lib/syslinux/modules/bios/libutil.c32 /data/tftpboot/ $ cp /path/to/menu.png /data/tftboot/
Now we need to create our menu. Under the pxelinux.cfg directory we will need to make a file called
default, which at this stage will look like this:
# Menu Entry for PXELINUX. Created 20170618 mvdw. UI vesamenu.c32 PROMPT 0 TIMEOUT 600 DEFAULT memtest86 # Later we will move this to a separate file to be INCLUDEd here: MENU TITLE Universal PXE Linux Bootloader MENU BACKGROUND menu.png MENU TABMSG http://www.vandewerken.com.au/blog/ MENU WIDTH 72 MENU MARGIN 10 MENU VSHIFT 3 MENU HSHIFT 6 MENU ROWS 15 MENU TABMSGROW 20 MENU TIMEOUTROW 22 menu color title 1;36;44 #66A0FF #00000000 none menu color hotsel 30;47 #C00000 #DDDDDDDD menu color sel 30;47 #000000 #FFFFFFFF menu color border 30;44 #D00000 #00000000 std menu color scrollbar 30;44 #DDDDDDDD #00000000 none # end include LABEL memtest86 menu label memtest86+-5.01 # menu indent 1 kernel /i386/memtest/memtest86+-5.01 #label Ubuntu Distributions # menu label Ubuntu Distributions -> # MENU INDENT 1 # CONFIG /menu/ubuntu.cfg #label System Tools # menu label System Tools -> # MENU INDENT 1 # CONFIG /menu/system.cfg
A couple of points about this file before we go on. Firstly, there is a whole stack of stuff in there that we will later take out into a separate file to make it cleaner and allow the sub-menus to also include it. Also, you can see that I've added the future menu items, but they're commented out for now - first we'll get memtest86 going then worry about more fancy configuration (sub-menus and the like).
Now we want to edit
/etc/dnsmasq.conf to enable the tftpserver portion without affecting either the local network DNS nor the local network DHCP. The default dnsmasq.conf file under Ubuntu 17.04 is completely commented out; we first back it up:
$ sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.bak
then replace it with the following:
# Configuration file for dnsmasq. # # Format is one option per line, legal options are the same # as the long options legal on the command line. See # "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details. # Disable DNS Server port=0 # Enable DHCP logging log-dhcp # Respond to PXE requests for the specified network; # run as DHCP proxy dhcp-range=192.168.29.0,proxy dhcp-boot=pxelinux.0 # Disable re-use of the DHCP servername and filename fields as extra # option space. That's to avoid confusing some old or broken DHCP clients. dhcp-no-override # PXE menu. The first part is the text displayed to the user. The second is the timeout, in seconds. pxe-prompt="Booting Network Client", 5 # Provide network boot option called "Network Boot". # The known types are x86PC, PC98, IA64_EFI, Alpha, Arc_x86, # Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI and X86-64_EFI # This option is first and will be the default if there is no input from the user. pxe-service=x86PC,"Network Boot",pxelinux # pxe-service=X86-64_EFI, "Network Boot x86-64 UEFI", <image-name> # pxe-service=Xscale_EFI, "Network Boot ARM", <image-name> enable-tftp tftp-root=/data/tftpboot
Note that I have put my network in on the line with
dhcp-range=; you will need to edit this to suit the network you have at your installation. Also note that for the moment we have only enabled x86 architecture - we will get to the other arches at a later stage but for now we will make sure we can boot it like this.
Now we need to make a quick hack to make sure our local dns on the server doesn't try to use its own dnsmasq, since we've disabled that functionality. To do this we edit
/etc/default/dnsmasq and add the following line at the end:
Run and Test!
Now we restart the dnsmasq service:
$ service dnsmasq start
and we should be able to boot any i386 architecture machine on the network and run memtest86. Note that you may have to setup the BIOS of the target machine to be able to boot from the network.
If you've been following along with this blog and comparing it to the excellent Manski.net version, you will see that it's very similar. That's true, but in the next instalment I will extend this to be able to boot other OSes than just memtest, and then we'll look into other architectures and images.
Thanks for reading, till next time.