More PXE Magic

In this article, I've decided to follow up on a topic I wrote about not in my column directly, but as a feature article called "PXE Magic" in the April 2008 issue. In that article, I talk about how to set up a PXE server from scratch, including how to install and configure DHCP and TFTP. Ultimately, I even provide a basic pxelinux configuration to get you started. Since then, PXE menus with pxelinux have become more sophisticated and graphical and could seem a bit intimidating if you are new to it. In this column, I explain how to piggyback off of the work the Debian and Ubuntu projects have done with their PXE configuration to make your own fancy PXE menu without much additional work. I know not everyone uses Debian or Ubuntu, so if you use a different distribution, hold off on the angry e-mail messages; you still can use the PXE configuration I'm showing here for your distro, provided it gives some basic examples of how to PXE boot its installer. Just use these steps as a launching off point and tweak the PXE config to work for you.

Simple Ubuntu PXE Menu

If this is your first time configuring a PXE server, for the first step, I recommend following my steps in the "PXE Magic" article to install and configure DHCP and TFTP. Otherwise, if you have existing servers in place, just make sure that DHCP is configured to point to your TFTP server (if it's on the same machine, that's fine). And, if you already have any sort of pxelinux configuration in your tftpboot directory, I recommend that you back it up and move it out of the way—I'm going to assume that your entire /var/lib/tftpboot (or /tftpboot on some systems) directory is empty to start with. For the rest of this article, I reference /var/lib/tftpboot as the location to store your PXE configuration files, so if you use /tftpboot, adjust the commands accordingly.

Both Debian and Ubuntu provide a nice all-in-one netboot configuration for each of their releases that makes it simple to PXE boot a particular release yourself. The file is called netboot.tar.gz and is located in a netboot directory along with the rest of the different install images. For instance, the netboot.tar.gz for the i386 Ubuntu 12.04 release (named Precise) can be found at http://us.archive.ubuntu.com/ubuntu/dists/precise/main/installer-i386/current/images/netboot/netboot.tar.gz.

To get started, cd to your tftpboot directory, and then use wget to pull down the netboot.tar.gz file (I'm assuming you'll need root permissions for all of these steps, so I'm putting sudo in front of all of my commands), and then extract the tarball:


$ cd /var/lib/tftpboot
$ sudo wget http://us.archive.ubuntu.com/ubuntu/dists/precise/
↪main/installer-i386/current/images/netboot/netboot.tar.gz
$ sudo tar xzf netboot.tar.gz
$ ls
netboot.tar.gz  pxelinux.0  pxelinux.cfg  
 ↪ubuntu-installer  version.info

As the ls command shows, an ubuntu-installer directory was created along with pxelinux.0 and pxelinux.cfg symlinks that point inside that ubuntu-installer directory to the real files. Without performing any additional configuration, provided your DHCP and TFTP servers were functioning, you could PXE boot a server with this configuration and get a boot menu like the one shown in Figure 1.

Figure 1. Ubuntu Precise PXE Boot Menu

Ubuntu has taken the extra steps of theming its PXE menu with its color scheme and even provided a logo. Unlike the PXE menu I demoed in my previous "PXE Magic" article, this menu functions more like a GUI program. You can use the arrow keys to navigate it, the Enter key to select a menu item and the Tab key to edit a menu entry.

Multi-OS PXE Menu

If all you were interested in was PXE booting a single version of Ubuntu or Debian, you would be done. Of course, what if you wanted the choice of either the 32- or 64-bit versions of a particular release, or what if you wanted to choose between a few different releases? Although you could just overwrite your tftpboot directory every time you wanted to change it up, with only a few extra tweaks to the config, you easily can host multiple releases with the same menu.

Move Precise to a Submenu

To get started, let's clean out any existing files in the /var/lib/tftpboot directory. Let's use the i386 Precise netboot.tar.gz to begin, but let's tweak how the files are organized by isolating precise in its own directory:


$ cd /var/lib/tftpboot
$ sudo mkdir precise
$ cd precise
$ sudo wget http://us.archive.ubuntu.com/ubuntu/dists/precise/
↪main/installer-i386/current/images/netboot/netboot.tar.gz
$ sudo tar xzf netboot.tar.gz

All of the interesting PXE configuration can be found inside the ubuntu-installer/i386 directory, so make a copy of those files back in the root tftpboot directory so you can edit them:


$ cd /var/lib/tftpboot
$ sudo cp -a precise/ubuntu-installer/i386/boot-screens 
 ↪precise/ubuntu-installer/i386/pxelinux.0 
 ↪precise/ubuntu-installer/i386/pxelinux.cfg .

Unfortunately, all of the configuration files under the boot-screens directory you copied reference ubuntu-installer/i386/boot-screens, when you want them to reference just boot-screens, so the next step is to run a quick Perl one-liner to search and remove any instance of ubuntu-installer/i386/ found in the config file:


$ cd /var/lib/tftpboot/boot-screens
$ sudo perl -pi -e 's|ubuntu-installer/i386/||' *

The specific pxelinux configuration that points to the Ubuntu Precise kernel and initrd can be found under precise/ubuntu-installer/i386/boot-screens/txt.cfg. If you were to look at that file, it would look something like this:


default install
label install
        menu label ^Install
        menu default
        kernel ubuntu-installer/i386/linux
        append vga=788 initrd=ubuntu-installer/i386/
        ↪initrd.gz -- quiet 
label cli
        menu label ^Command-line install
        kernel ubuntu-installer/i386/linux
        append tasks=standard pkgsel/language-pack-patterns= 
         ↪pkgsel/install-language-support=false vga=788 
         ↪initrd=ubuntu-installer/i386/initrd.gz -- quiet

What you want to do is make a copy of this config file under your root-level boot-screens directory, but because you extracted the tarball into a directory named precise (instead of the root directory), you need to do another search and replace, and add precise in front of any reference to the ubuntu-installer directory. Otherwise, the paths to the kernel and initrd will be wrong:


$ cd /var/lib/tftpboot/boot-screens
$ sudo cp ../precise/ubuntu-installer/i386/boot-screens/txt.cfg 
 ↪precise-i386.cfg
$ sudo perl -pi -e 's|ubuntu-installer|precise/ubuntu-installer|g' 
 ↪precise-i386.cfg

When you are done, the /var/lib/tftpboot/boot-screens/precise-i386.cfg file should look something like this:


default install
label install
        menu label ^Install
        menu default
        kernel precise/ubuntu-installer/i386/linux
        append vga=788 initrd=precise/ubuntu-installer/i386/initrd.gz 
         ↪-- quiet 
label cli
        menu label ^Command-line install
        kernel precise/ubuntu-installer/i386/linux
        append tasks=standard pkgsel/language-pack-patterns= 
         ↪pkgsel/install-language-support=false vga=788 
         ↪initrd=precise/ubuntu-installer/i386/initrd.gz -- quiet

Finally, open up /var/lib/tftpboot/boot-screens/menu.cfg in your favorite text editor. This file contains the bulk of the configuration that has to do with the PXE menu system, and the file should look something like this:


menu hshift 13
menu width 49
menu margin 8

menu title Installer boot menu^G
include boot-screens/stdmenu.cfg
include boot-screens/txt.cfg
include boot-screens/gtk.cfg
menu begin advanced
        menu title Advanced options
        include boot-screens/stdmenu.cfg
        label mainmenu
                menu label ^Back..
                menu exit
        include boot-screens/adtxt.cfg
        include boot-screens/adgtk.cfg
menu end
label help
        menu label ^Help
        text help
   Display help screens; type 'menu' at boot prompt to 
    ↪return to this menu
        endtext
        config boot-screens/prompt.cfg

What you want to do is replace the include boot-screens/txt.cfg line with a submenu that points to the new precise-i386.cfg file you created. I used the existing advanced submenu as an example to start from. The resulting file should look like this:


menu hshift 13
menu width 49
menu margin 8

menu title Installer boot menu^G
include boot-screens/stdmenu.cfg
menu begin precise-i386
        menu title Precise 12.04 i386
        include boot-screens/stdmenu.cfg
        label mainmenu
                menu label ^Back..
                menu exit
        include boot-screens/precise-i386.cfg
menu end
include boot-screens/gtk.cfg
menu begin advanced
        menu title Advanced options
        include boot-screens/stdmenu.cfg
        label mainmenu
                menu label ^Back..
                menu exit
        include boot-screens/adtxt.cfg
        include boot-screens/adgtk.cfg
menu end
label help
        menu label ^Help
        text help
   Display help screens; type 'menu' at boot prompt to 
    ↪return to this menu
        endtext
        config boot-screens/prompt.cfg

When you PXE boot now, you should see a menu option labeled Precise 12.04 i386, as shown in Figure 2. When you select that option and press Enter, you then can access the standard install options like before.

Figure 2. Precise in a Submenu

Add Precise 64-Bit

Now that you have the 32-bit Precise install working, let's add the 64-bit release as well. You'll basically perform the same initial steps as before, after you remove any existing netboot.tar.gz files. The netboot.tar.gz file is structured so that it will be safe to extract it in the same precise directory:


$ cd /var/lib/tftpboot/precise
$ sudo rm netboot.tar.gz
$ sudo wget http://us.archive.ubuntu.com/ubuntu/dists/precise/
↪main/installer-amd64/current/images/netboot/netboot.tar.gz
$ sudo tar xzf netboot.tar.gz

Since you already copied over the boot-screens directory, you can skip ahead to copying and modifying the 64-bit txt.cfg, so it gets pointed to the right directory:


$ cd /var/lib/tftpboot/boot-screens
$ sudo cp ../precise/ubuntu-installer/amd64/boot-screens/txt.cfg 
 ↪precise-amd64.cfg
$ sudo perl -pi -e 's|ubuntu-installer|precise/ubuntu-installer|g' 
 ↪precise-amd64.cfg

Now, open up /var/lib/tftpboot/boot-screens/menu.cfg again, and add an additional menu entry that points to the precise-amd64.cfg file you created. The file ends up looking like this:


menu hshift 13
menu width 49
menu margin 8

menu title Installer boot menu^G
include boot-screens/stdmenu.cfg
menu begin precise-i386
        menu title Precise 12.04 i386
        include boot-screens/stdmenu.cfg
        label mainmenu
                menu label ^Back..
                menu exit
        include boot-screens/precise-i386.cfg
menu end
menu begin precise-amd64
        menu title Precise 12.04 amd64
        include boot-screens/stdmenu.cfg
        label mainmenu
                menu label ^Back..
                menu exit
        include boot-screens/precise-amd64.cfg
menu end
include boot-screens/gtk.cfg
menu begin advanced
        menu title Advanced options
        include boot-screens/stdmenu.cfg
        label mainmenu
                menu label ^Back..
                menu exit
        include boot-screens/adtxt.cfg
        include boot-screens/adgtk.cfg
menu end
label help
        menu label ^Help
        text help
   Display help screens; type 'menu' at boot prompt to 
    ↪return to this menu
        endtext
        config boot-screens/prompt.cfg
Add a New Ubuntu Release

So, you were happy with your 12.04 PXE menu, and then Ubuntu released 12.10 Quantal, so now you want to add the 32-bit version of that to your menu. Simply adapt the steps from before to this new release. First, create a directory to store the new release, and pull down and extract the new netboot.tar.gz file:


$ cd /var/lib/tftpboot
$ sudo mkdir quantal
$ cd quantal
$ sudo wget http://us.archive.ubuntu.com/ubuntu/dists/quantal/
↪main/installer-i386/current/images/netboot/netboot.tar.gz
$ sudo tar xzf netboot.tar.gz

Next, copy over the quantal txt.cfg file to your root boot-screens directory, and run a Perl one-liner on it to point it to the right directory:


$ cd /var/lib/tftpboot/boot-screens
$ sudo cp ../quantal/ubuntu-installer/i386/boot-screens/txt.cfg 
 ↪quantal-i386.cfg
$ sudo perl -pi -e 's|ubuntu-installer|quantal/ubuntu-installer|g' 
 ↪quantal-i386.cfg

Finally, edit /var/lib/tftpboot/boot-screens/menu.cfg again, and add the additional menu entry that points to the quantal-i386.cfg file you created. The additional section you should put below the previous submenus looks like this:


menu begin quantal-i386
        menu title Quantal 12.10 i386
        include boot-screens/stdmenu.cfg
        label mainmenu
                menu label ^Back..
                menu exit
        include boot-screens/quantal-i386.cfg
menu end

The resulting PXE menu should look something like Figure 3. To add the 64-bit release, just adapt the steps from the above Precise 64-bit release to Quantal. Finally, if you want to mix and match Debian releases as well, the steps are just about the same, except you will need to track down the Debian netboot.tar.gz from its project mirrors and substitute precise for Debian project names like squeeze. Also, everywhere you see a search and replace that references ubuntu-installer, you will change that to debian-installer.

Figure 3. Now with Three Options

Kyle Rankin is a Tech Editor and columnist at Linux Journal and the Chief Security Officer at Purism. He is the author of Linux Hardening in Hostile Networks, DevOps Troubleshooting, The Official Ubuntu Server Book, Knoppix Hacks, Knoppix Pocket Reference, Linux Multimedia Hacks and Ubuntu Hacks, and also a contributor to a number of other O'Reilly books. Rankin speaks frequently on security and open-source software including at BsidesLV, O'Reilly Security Conference, OSCON, SCALE, CactusCon, Linux World Expo and Penguicon. You can follow him at @kylerankin.

Load Disqus comments