OS Deployment

Installing TFTP-HPA and PXELinux

Two things are needed to get a system to PXE boot: a DHCP server and a TFTP server. This can be the same system, or it can be two separate systems. If you’re integrating a new TFTP server into an existing network that already has a DHCP server, it’s probably better if you keep the systems separate; otherwise, I’d recommend setting up a single Linux system with both the DHCP server and TFTP server.

DHCP Warning

Keep in mind that you should only have a single DHCP server running on a given network. If you setup an additional DHCP server on a single network, it is extremely likely that you will break DHCP for ALL systems on that network. Make sure that you know your network’s layout, and whether or not there’s an existing DHCP server running.

If you just want to experiment with this stuff, get yourself a hefty workstation with lots of RAM (2-4GB), a decent processor (anything current will do), and a lot of disk space (a typical Fedora Core installation requires about 4GB of disk, and you’ll want some extra room to store your installation media, so at least 15GB should do the trick), and use VirtualBox (or VMWare Workstation/Fusion/Server) to setup a virtual machine running Linux. This system can then be used as a DHCP and TFTP server for a private network within VirtualBox, thus isolating your environment from the rest of the network. You can then create a second virtual machine that can be used as your PXE client.

If you’re looking to implement this on a corporate network, be sure to ask your network administrator(s) for permission beforehand. In addition to ensuring that it’s ok to implement, your network administrator will very likely have good advice for how to set this sort of thing up – and, even if they don’t, at least they’ll know what’s going on when all hell breaks loose because the DHCP server has stopped responding or has started handing out invalid leases…

In a hurry? Take a look at the TFTP summary instead.

I’ve used both ISC dhcpd and Microsoft’s DHCP server to successfully boot a system using tftpd-hpa on both Ubuntu and Gentoo Linux. I’ve even managed to run this setup on a Linksys NSLU2, so the underlying hardware requirements are pretty minimal. There’s tons of tutorials for how to setup PXE booting using Windows-only solutions, but I highly recommend running tftpd-hpa on Ubuntu. It’s easy to setup and maintain, and it’s proven to be rock-solid over the last few years.

First things first, though. Let’s get a TFTP server up and running.

Find a system that you can install and run tftpd-hpa on. As I said earlier, the Ubuntu package has performed rock-solid for me since Ubuntu 7.04, and I’m currently running Ubuntu 8.04. Note that this can be done in a virtual machine, as long as the system is using bridged networking. I’ve run my TFTP server on physical hardware (on anything from a Dell Optiplex GX150 wtih 256MB RAM to a PowerEdge 1950 with 16GB of RAM), as well as VMWare ESX/Workstation (on Windows) and VirtualBox (on a stock Mac Mini running OS X 10.4/10.5) virtual machines. As long as the system can be accessed from your network by IP address (name resolution won’t be available during a PXE boot, so it’s not worth ensuring that the TFTP server’s name can be resolved), it’ll do just fine.

Configuring tftpd-hpa

The -s option specifies the root directory for the TFTP server; in other words, this is the directory from which all files will be sent from. Any relative path specified by a TFTP client will be rooted here; files above this folder will not be accessible to any TFTP client.

The -m option allows you to specify a set of “remapping rules”, allowing you to correct the mixed-case filenames requested by some (in my opinion) broken TFTP clients (*cough* Windows PE *cough*). The easiest way to get Windows PE to PXE boot from a non-Windows TFTP server is via the remapping rules, as you’ll see once I get to the Microsoft Deployment Toolkit stuff for deploying Windows.


Install tftpd-hpa by running:

emerge -av tftp-hpa

You’ll want to either edit /etc/conf.d/in.tftpd, where the -s parameter equates with INTFTPD_PATH. Note that you’ll have to add the -m parameter to the INTFTPD_OPTS value. You’ll also need to run:

rc-update add in.tftpd default

…or do it the lazy way and just add the entire command line to /etc/conf.d/local.start like so:

/usr/sbin/in.tftpd -s /var/lib/tftpboot -m /var/lib/tftpboot/pxelinux.cfg/remap


Install tftpd-hpa by running:

apt-get install tftpd-hpa

Edit /etc/xinetd.d/tftp (or create it if it doesn’t exist), using the following as a guide:

service tftp
    disable = no
    wait = yes
    user = root
    socket_type = dgram
    protocol = udp
    server = /usr/sbin/in.tftpd
    server_args = -m <remapping rules file> -s <TFTP server root>

Other Distributions

For other distributions, simply install xinetd and tftpd-hpa however you like, and use the Ubuntu xinetd configuration file above.

The TFTP Remap File

If you’re running tftp-hpa on a Linux system, you have to keep in mind the fact that most (if not all) Linux filesystems are case-sensitive (unlike Windows filesystems like FAT16/32 or NTFS). If you’re planning on installing Windows over the network using the Microsoft Deployment Toolkit (which I highly recommend using if you want to install Windows with ease), then you’ll eventually run into the fun fact that Microsoft’s Windows PE bootloader uses hard-coded, mixed-case filenames and paths inconsistently during the PXE boot process. This tiny little niggle caused me nearly a week’s worth of headaches and swearing before I found a simple work-around: tftp-hpa’s file remapping feature. The only problem that I had was that it’s not very well documented, and the few examples I could find online were uniformly over-complicated.

Here’s the simplest solution that I could come up with:

  1. create /var/lib/tftpboot/pxelinux.cfg/remap using your favorite text editor, with the following contents:
    rg \\ /
    rg ([A-Z]) \L\1
  2. modify the command-line arguments for tftpd-hpa to include -m /var/lib/tftpboot/pxelinux.cfg/remap.
  3. ensure that all of the files and folders below /var/lib/tftpboot/ are lower-case, rather than mixed- or upper-case. You can use this bash script to do this quickly and easily, once you have all of your files in place (or whenever you add new files to the tree) – just ignore any of the warnings (and there will be a warning for each file that’s already lower-case):
    for i in `find /var/lib/tftpboot/ -type d && find /var/lib/tftpboot/ -type f`; do
          mv $i `echo $i | tr [:upper:] [:lower:]`

The TFTP remap file tells tftp-hpa to:

  1. rg \\ /: replace backslashes (\) in the requested filename with forward-slashes (/); this is really only useful if your TFTP server is running on Linux, where the path separator is the forward-slash. If you were running this on Windows, you would need to use rg / \\ instead;
  2. rg ([A-Z]) \L\1: replace any uppercase letters in the requested filename with the lowercase version instead. This avoids the problem of case-sensitivity in Linux filesystems; again, this is only needed if the TFTP server root is located on a case-sensitive filesystem (like ext2/ext3/reiserfs), and is probably unnecessary on a Windows TFTP server.

Most of the solutions I’ve found on other websites have an entry per file, which I figure will eventually be unmaintainable as you add boot images to the TFTP server. The above solution requires no maintenance, as long as you ensure that all of your files and folders under /var/lib/tftpboot/ are lowercase.

I typically save my remap file as /var/lib/tftpboot/pxelinux.cfg/remap, so that if I ever need to move my TFTP server somewhere, I can just zip up the entire /var/lib/tftpboot tree.


Despite its name, PXELinux (apparently) has nothing to do with Linux, beyond being able to boot it. PXELinux is an extremely configurable, PXE-capable bootloader, and is part of Syslinux. You’ll want to download the latest version (or install it using your appropriate package manager), and copy pxelinux.0, memdisk, menu.c32, and vesamenu.c32 to your TFTP server’s root directory (the directory specified after the -s parameter in tftpd-hpa’s command line). At first, we will only use pxelinux.0; as our setup grows, I’ll be adding in the other files. For now, though, just make sure you have a copy of the files in the right location.

PXELinux can have any number of configuration files. It is hard-coded to look for its configuration files at boot in a folder called pxelinux.cfg. Create this folder using:

mkdir -p /var/lib/tftpboot/pxelinux.cfg/

I’ll describe the configuration files that will go into this folder later.


Install PXELinux by running:

emerge -av syslinux

The files you need will be located in /usr/share/syslinux/. Copy or symlink the files to your TFTP server root directory.


Install PXELinux by running:

apt-get install syslinux

The files you need will be located in /usr/lib/syslinux.

syslinux Warning

The version of Syslinux included in most Linux distributions tends to lag extremely far behind the official releases, so you’ll likely want to download a copy instead. Note that you don’t need to compile the syslinux release on your own: precompiled binaries are included in the release, so you’ll just need to download and extract the latest release to a temporary folder, and copy the appropriate files to your TFTP server’s root directory.

Ubuntu is almost always significantly out of date (3.53 at the time of writing), while Gentoo is fairly up to date (version 3.73 at the time of writing). Currently, 3.80 has only been available for about two weeks.

The instructions I’ll provide for configuring PXELinux using vesamenu.c32 will NOT work with the current Ubuntu package. You will need at least version 3.73 for my instructions to work, but if you don’t care about the fancy menu capabilities provided by vesamenu.c32, you’ll be fine using the Ubuntu package.

Testing the TFTP Server

Make sure your TFTP server is running (/etc/init.d/in.tftpd start on Gentoo; /etc/init.d/xinetd start if you’re using Ubuntu/xinetd), and use a TFTP client to download pxelinux.0 from your TFTP server.

  • from Windows XP or later, open a command prompt, and run tftp <server IP> get pxelinux.0
  • from Linux, run tftp <server IP> -c get pxelinux.0

Note that on Ubuntu, the tftp-hpa package is split into client and server components; you’ll need to install the client component if you want the above command to work (apt-get install tftp-hpa – as opposed to the earlier apt-get install tftpd-hpa). Gentoo builds and installs both client and server by default. Other distributions may differ.

If you receive no errors, you should have a file on your test host called pxelinux.0. Congratulations: you’re done the easy part. If you do run into errors, you should probably add -v one or more times to the tftpd-hpa command line, and examine your syslog output. Once you’ve added the -v and retry the download of pxelinux.0, you should be able to see the filename that the client is requesting and whether or not it was sent in your syslog output. This makes it FAR easier to debug your setup; I tend to use -v -v when I’m trying to resolve problems.

Next Time…

I’ll describe how to setup your DHCP server, and configure PXELinux so that you can actually start PXE booting.

One reply on “Installing TFTP-HPA and PXELinux”

Thank you very much for the tftp-hpa lower case remap tip! Just beware, your ‘mv $i `echo $i | tr [:upper:] [:lower:]`’ script is ‘find’-ing the directories not by their hierarchy. So if you have for example SYSTEM32/DRIVERS, it finds SYSTEM32/DRIVERS first, tries to rename it to system32/drivers by it can’t because it should rename SYSTEM32 to system32 first! You can’t mv the directory to nonexistent parent directory! So instead of improving the script I just ran it a few times, until it says ‘file is the same’ all the time.

Comments are closed.