PXE netinstalling for simpletons

Since posting this article I have found a much easier way to do this. This article is still great background information and goes into more detail if you want to take this further, but you should consider reading my new article.

Well, I promised something technical and here it is. It’s turned into a bit of a mammoth post, but the end result is pretty cool!

The idea of being able to install your favourite Linux distro over the network and so do away with burning CD’s (which ultimately get used once and then thrown away) is tantalizing. Not to mention the serious geek points for anyone who has a boot server on their network.

I started out using this article as a reference, as the process seemed relatively simple. However, I soon found out that this article wasn’t strictly accurate and didn’t explain some things too brilliantly! So I decided to see if I could do better.

The following is my account of setting up my own boot server on a spare box I had lying around (though you can just as easily do it on your main computer). I started from a base install of Ubuntu Server 8.10 (Intrepid Ibex) which I installed in the normal way (i.e. from a CD).


Once my server was up and running and I could ssh into it, the fun really started. The article I linked to above tells you what you need, namely:

  1. A dhcp server (sudo apt-get install dhcp3-server)
  2. An Ubuntu CD image (the alternate CD not the live CD one, though presumably the server version works too).
  3. A TFTP server (more on this below)
  4. A web server, such as apache (sudo apt-get install apache2)

Out of those, only the TFTP server caused me problems, I dutifully installed the suggested package (tftpd), only to find much later that it didn’t support one of the options needed by the bootloader.  To avoid this use the tftpd-hpa package instead (sudo apt-get install tftpd-hpa).

What happens…

At this stage, it might help if I run through the actual netbooting process as this will give you a general understanding of what we need to configure:

  1. When you choose the netboot option on the machine you want to boot (usually in the boot order settings in the bios), the bios will run a small program stored in on the motherboard (PXE-ROM). This program is essentially a DHCP client, which sends out broadcasts on the network looking for someone to provide it with an IP address and information on what to do next.
  2. The DHCP server on your network respond to the broadcast and dishes out an IP address to the client. It also passes it the IP address of a boot server and the name of the bootloader file to request.
  3. The client contacts the boot server (which can actually be the same machine as the DHCP server) and requests the bootloader file and executes it.
  4. The bootloader loads it’s configuration from the server and displays a menu of the boot options.
  5. When the user selects an option, the bootloader requests the kernel and initrd images from the server and boots the kernel.

Our kernel will run the Ubuntu installer so that we can install an Ubuntu system on the client machine, but to get the packages we will use apache to serve them out for us across the network.

Let’s get down to it

OK, let’s configure some stuff, first up is the DHCP server. Here’s my configuration:

default-lease-time 600;
max-lease-time 7200;
option subnet-mask;
option broadcast-address;
option routers;
option domain-name-servers <ns1>, <ns2>;
option domain-name "mydomain.com";
subnet netmask {
filename "pxelinux.0";

This goes in /etc/dhcp3/dhcpd.conf (sudo nano /etc/dhcp3/dhcpd.conf). I’m actually only going to expalin the last two lines (the rest is pretty standard DHCP stuff which you can find out about somewhere else. The last two lines are expalined below:

  1. next-server; – gives the client the address of your boot server, in most cases this will be the same as your DHCP server address (I’m running all this on my one server box). Change the address to the address of the machine you want to use.
  2. filename “pxelinux.0”; – the bootloader file to use, just leave this as it is.

Once you’ve done that, restart the DHCP server with ‘sudo /etc/init.d/dhcp3-server restart’. Also if you’re running a commercial (wireless) router, you’ll need to disable the DHCP server on the router from it’s control panel.

TFTP or not TFTP

The TFTP server needs very little configuration. All I did was create directory in the root of my filesystem to serve from:

sudo mkdir /tftpboot

Then you just need to make sure that tftpd serves from that directory (I spent ages wondering why mine wasn’t working because of this!), by changing the ftpd line in /etc/inetd.conf to:

tftp           dgram   udp     wait    root  /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /tftpboot

(I basically changed the path at the end). Then restart the inetd service (sudo /etc/init.d/openbsd-inetd restart).

Serving the iso files from Apache

Now we’re going to copy everything out of the iso image to somewhere that Apache can find it:

sudo mkdir -p /var/www/netinstall/ubuntu8.10-alternate
sudo mount -o loop ubuntu-8.10-alternate.iso /mnt
sudo cp -a /mnt/* /var/www/netinstall/ubuntu8.10-alternate/
sudo umount /mnt

First, we made the required directories to serve our files from. Structuring the directories like this allows us to serve other versions out from the same server if we want to. Secondly, we mounted the iso file on the /mnt directory, then we copied all the files from that to our server directory and finally unmounted the iso image.

If you now go to http://<serveraddress>/netinstall/ubuntu8.10-alternate, you should see a listing of the files that were on the CD. That was easy, let’s move on.

The elusive pxelinux.0

You should recognise ‘pxelinux.o’ from the filename perameter in the DHCP config above, this is the bootloader that loads our kernel. Unfortunately, I couldn’t find it (and the other article gave me no clue!).  I eventually found it in the files I copied from the iso (I’ve since learned that you can also get it from the ‘syslinux’ package). To copy it to the correct place use:

sudo cp /var/www/netinstall/ubuntu8.10-alternate/install/netboot/pxelinux.0 /tftpboot/

Next we need a kernel and initrd image we’ll also get these from the files we just copied:

sudo mkdir /tftpboot/ubuntu8.10-alternate
sudo cp /var/www/net
install/ubuntu8.10-alternate/install/netboot/ubuntu-installer/i386/linux /tftpboot/ubuntu8.10-alternate/
sudo cp /var/www/net
install/ubuntu8.10-alternate/install/netboot/ubuntu-installer/i386/initrd.gz /tftpboot/ubuntu8.10-alternate/

Now we need to configure pxelinux to find our kernel, the configuration goes in /tftpboot/pxelinux.cfg/default:

default 1
timeout 200
prompt 1
display pxelinux.cfg/msgs/boot.msg
# begin list of available boot options
# Local hard disk boot
label 1
localboot 0
# Ubuntu 8.10 Alternate install CD
label 2
kernel ubuntu8.10-alternate/linux
append initrd=ubuntu8.10-alternate/initrd.gz

The first two lines select the default boot entry (see below) to use and give us a timeout of 20 seconds after which that option will be selected (the timout value is measure in tenths of a second). The next two display a menu of the available kernels (which goes in /tftpboot/pxelinux.cfg/msgs/boot.msg).

Next we have our boot entries. Each of  these have a label line which enables us to identify the listing later. The first listing just has a directive telling pxelinux to boot from the local hard disk. As this option is selected as the default (above) the computer will attempt to boot from it’s hard disk once the timout has occured.

The second listing is more interesting, we have the kernel directive with the path relative to the /tftpboot/ directory, this tells  pxelinux what kernel should be booted if this option is selected (duh!). We have the append line, which adds options to the kernel, in this case we tell it to use our initrd  image, but you can add any valid kernel option. Obviously this file can have as many listing as you want to give boot options, there’s also support for multiple different menu’s and help screen, but I’m keeping it at this for now.

OK, now all we need is our display message. I put mine in the msgs directory (mkdir /tftpboot/pxelinux.o/msgs) and put this in the  file  (boot.msg):

^Y^L                  ^O0fNETWORK BOOT OPTIONS^O07
Select one of the options below, or press enter for the default:
1 - Local Hard disk boot [Default]
2 - Install Ubuntu 8.10 'Intrepid Ibex'
NB: Default will be selected after 20 seconds

That’s it! Just make sure the bit before the hyphen matches the label field we used above, so that the user knows what to type at the prompt. The funny characters in the file correspond to specially interpreted charaters for clearing the screen, etc. I just copied them from another file!

Booting Clients

The first client I tried to boot was my ASUS EeePC 901. I succesfully configured the bios to boot from the network and got to the menu screen. Booting the Ubuntu kernel worked and I was able to get into the installer, however a few steps in it told me that my ethernet adaptor was unsupported so it was unable to get packages for installation. Apparently, the next version of Ubuntu (Jaunty) is going to have the driver included by default in it’s kernel, so maybe that’ll work (I’ll try it at some point and report back).

Next I decided it would be cool to try and boot a virtual machine from my network. Having done some research I found that if I used VirtualBox with host networking I should be able to get an IP address from my network (rather than VirtualBox’s build in DHCP) and so boot from the network. I currently had the Open Source edition of VirtualBox installed, which is an older version (2.04) which doesn’t support host based networking without a lot of fiddling around.

I decided to take the easy way out and upgraded to version 2.1 via the VirtualBox repository. Once this was installed I was able to select ‘Host Network Interface’ in the virtual machine network settings and then select eth0 as my interface. In the advanced settings I set network as the first boot device and then booted the machine:

Network boot screen, as seen in VirtualBox

Network boot screen, as seen in VirtualBox

As  you can see from the screenshot, this worked just fine, as did proceeding to the installer. When I reached the step in the install which asked me to select a mirror I scrolled up and selected ”. On the next few screens I had to enter information about the server I was using, namely the IP address ( and the path to the repository (/netinstall/ubuntu8.10-alternate/). See the screenshots below for details:

Select 'enter information manually' on the repository selection screen.

Select 'enter information manually' on the repository selection screen.

Enter the IP address of the webserver where you copied the files from the ISO

Enter the IP address of the webserver where you copied the files from the ISO

Enther the path of the directory which you copied the files to, relative to the web server root.

Enther the path of the directory which you copied the files to, relative to the web server root.

The rest of the install proceeded just fine, with the packages being retrieved and installed from the network. I ended up with a functional desktop system (in a virtual machine) just as I would get if I had used a CD.

Next Steps…

Wow, that turned out to be pretty long. Hopefully you’ve made it this far and I’ve managed to help you get to grips with this. I still have a few things I want to try to setup with this and I’ll report back if I make any progress:

  • It would be really great to have Clonezilla and/or some kind of rescue toolkit distribution available for booting over the network, that way I can just plug in a machine and boot up whatever I need.
  • I eventually want to have a go at making a completely diskless system, which doesn’t look that difficult as I seem to have done most of the work. Ideally it would be nice to be able to install/design a system in a virtual machine on my desktop and then deploy it across the network when it’s ready!

I hope you’ve enjoyed this How-To and have found it informative, if you have any problems, corrections or just want to say thanks, feel free to post a comment. Bye for now!

6 thoughts on “PXE netinstalling for simpletons

  1. hornet says:

    Thank you, mate. Nice and interesting article.

    I like this approach in a different way, pxe boot from a virtualbox OS image (server) in order to provide network based virtualized desktops for business employees.

    Methodology would be pretty the same you tested here, my concern is how to allocate consecutive pxe clients to a pool of virtual machines in the server (i.e. Should VM1 is busy, jump to VM2 and boot from it), or just boot from specific VMx which has your personal settings.

    This way, end users would be able to select XP, linux, forensics, etc. at boot time.

    BTW I got a 901 too, nice toy indeed.

    Bye for now

  2. Rob Connolly says:

    Hi Hornet,

    Thanks for the comments.

    Looks like you’re looking more at a thin client kind of solution. In my setup the server is just used as a file server, the code is actually running on the client.

    You could just setup a system which allows booting of multiple different OSes but mount all the filesystems over the network (see the Diskless Ubuntu article I linked to). Then the home filesystem holding user documents and setting can be shared between multiple OSes.

    And yes, the 901 is a really great toy!



  3. trouserless says:

    Great Howto! Got me up and going in short time…one comment is that the apache root is described as /netboot/ubuntu8.10-alternate/ in the apache2 and tftp config yet the example you give with virtualbox displays /netinstall/ubuntu8.10-alternate/ for the install dir…the difference between netboot/netinstall is subtle but critical!

    very nice work tho…clear and concise

  4. It stands for Virtual Private Network and you need Software to do it and truthfully you don’t need it. This is for high profile Corperate Networks that are anal about security.

  5. richard says:

    hi Rob,
    i met error when installing ubuntu 10.04 x64 from PXE, after i set mirror server IP and share path, i still couldn’t get “Bad archive mirror” message, “The specified ubuntu mirror is either not available, or does not have a valid Release file on it”. however, i tried to get file manually by “wget xxx”, it’s ok. have you seen similar issue? thanks

Leave a Reply

Your email address will not be published. Required fields are marked *