Funding for 'IT Lab' Project, Phase 1: Progress of sticker sales. Purchase a sticker to help us reach our target.Updated: 2010-02-28 11:53
Pixie booting with Ubuntu
Network booting has been around for quite some time now and involves booting one or more clients with an Operating System that is downloaded over the local network as opposed to from a local hard disk. In such a setup an internal hard disk is not required. Instead in its place lies a network shared drive. Therefore such a client is often referred to as a diskless node or a thin client.
Setting up a diskless clients has several advantages over a conventional desktop computer. For a large deployment consisting of hundreds of computers, a centralized OS that gets downloaded to the client is a lot easier to maintain than having to patch, upgrade and install a new piece of software across several machines. Also the absence of a hard disk means less chance for a hardware failure and less power consumption. Backing up data is much simplified due to it all being stored centrally. Thats not to say there aren't disadvantages but lets not get into it and demotivate our selves.
Early implementations of network booting required a method known as “Etherboot”, where a network aware boot loader had to be burnt (flashed) on to the network card's EPROM, thus overwriting or modifying it's stock firmware. As one might guess, this process is somewhat complicated and risky and should not be attempted unless you have the gear and know how.
Fortunately today we no longer have to deal with Etherbooting, thanks to the efforts by Intel to standardize network booting in the form of Preboot eXecution Environmen or PXE (pronounced pixie). Its safe to say that pretty much all modern network cards and motherboards produced in the last 5 years support PXE booting, thus giving us an opportunity to experiment with the technology. For those that are older or don't have PXE, checkout the reference section for a workaround.
In this article, we will attempt to setup a PXE bootable Ubuntu desktop environment where by you boot up a full graphical Ubuntu OS over the network. I will highlight two approaches of achieving this but will focus more on the experimental approach I'm currently working on. Note that the setup highlighted in this article is for educational purpose only and not secure enough for production use. Security has to be tightened and other aspects improved before it can be deployed in a LAN environment.
PXE booting and what is involved
It is always good to have at least a basic understanding of how PXE boot operates before we proceed with the setup. A personal computer's boot process is governed by the BIOS, where the BIOS supports several bootable media such as CDROM, USB drives, Hard Drives and the subject of our discussion PXE. Therefore in order to perform PXE booting on the client machine, you would have to configure its boot sequence by giving PXE a higher boot priority.
Once the PXE boot is initiated, the boot process will begin by sending out a DHCP request onto the network. At this point a PXE aware DHCP server should respond to the client (via the client's MAC address), issuing it an IP address and other network settings along with the IP address of the TFTP server and path of the file (TFTP payload) to download.
Upon receiving the DHCP response the client configures its network interface and proceeds to connect the TFTP server. This server is capable of serving a file over the Trivial File Transfer Protocol (TFTP) with no authentication required (hence trivial). In our case, we will push the PXE boot loader (pxelinux.0) to the network client. This boot loader will fetch its configuration file over TFTP and proceed to download the Linux kernel and Initial RAM disk (initrd) image required for booting the Linux OS.
While I won't go into the intricacies of the Linux boot process due to space limitations (perhaps I'll cover in a future article), I will state that the key difference of the network aware Linux boot process is that instead of looking for a local disk to mount as the root device, the kernel/initrd is configured to mount the root device over the network via the Network File System (NFS). Once the root has been mounted everything else is as expected and no different from a local hard drive based boot, with the minor exception that at no point should the client try to do a fresh DHCP request and obtain a different IP address (more on this later).
Setting up PXE boot server on Ubuntu
Finally we get to the meat of this article where we will configure the DHCP/TFTP/NFS services required for PXE boot. For this we will use just one server to host all the required services. It is assumed you have already installed Ubuntu on a single partition, on the machine which will act as the PXE boot server and assigned it a static IP address of 192.168.2.1 to eth0. Steps for PXE server setup are as follows (adopted from the DisklessUbuntuHowto, see Reference section)
1) Install the required packages
sudo apt-get install dhcp3-server tftpd-hpa syslinux initramfs-tools nfs-kernel-server
Above line will install the DHCP server, TFTP server, a package containing the PXE boot loader (pxelinux.0), a package containing a tool to generate the initrd image and finally the NFS server.
2) Configure your DHCP server
We need to set up the DHCP server to offer /tftpboot/pxelinux.0 payload along with network settings. Your dhcpd.conf might look like this assuming your subnet is 192.168.2.0
allow booting;
allow bootp;
subnet 192.168.2.0 netmask 255.255.255.0 {
range 192.168.2.100 192.168.2.200;
option broadcast-address 192.168.2.255;
option routers 192.168.2.1;
option domain-name-servers 192.168.2.1;
filename "/pxelinux.0";
}
3. Configure the TFTP Server
We need to set tftp-hpa to run in daemon mode and to use /tftpboot as its root directory.
Here is an example /etc/default/tftpd-hpa file
#Defaults for tftpd-hpa
RUN_DAEMON="yes"
OPTIONS="-l -s /tftpboot"
Configure tftp root directory
- Create directories
sudo mkdir -p /tftpboot/pxelinux.cfg
- Copy across PXE bootfile and Linux kernel. Note we use uname -r to get the running kernel version.
sudo cp /usr/lib/syslinux/pxelinux.0 /tftpboot
sudo cp /boot/vmlinuz-`uname -r` /tftpboot/vmlinuz
- Create default configuration file /tftpboot/pxelinux.cfg/default. We pass the root device via nfsroot and force to go to runlevel 5 which we will use to customize client services.
LABEL linux
KERNEL vmlinuz
APPEND root=/dev/nfs initrd=initrd.img nfsroot=192.168.2.1:/ ip=dhcp rw 5
- Set permissions
sudo chmod -R 777 /tftpboot
NOTE: If the files do not have the correct permissions you will receive a "File Not Found" or "Permission Denied" error.
4. Creating an Initrd suitable for mounting root over NFS
The Initrd is a temporary RAM disk which the kernel mounts as temporary root (/), until it can find the real root device, which is generally a hard disk partition. Therefore we must create an initrd capable of mounting root (/) over NFS.
a. Edit /etc/initramfs-tools/initramfs.conf
MODULES=most
#BOOT=local
BOOT=nfs
DEVICE=eth0
#NFSROOT=auto
NFSROOT=192.168.2.1:/
b. Create a new initrd and place it in /tftpboot
mkinitramfs -o /tftpboot/initrd.img `uname -r`
5. Configure NFS Server
A bit of explanation is required here, as I deviate from the DisklessUbuntuHowto. In that howto, it shows how you can boot a different Ubuntu setup server over NFS to the diskless client. I wanted to serve the same Ubuntu setup as that of the server. This is a bit more challenging as our server has to now act as a client. Therefore I ended up exporting the entire root file system over NFS.
But this causes a complication with the /etc directory. Sharing the server's /etc with the client can lead to overwriting of key configuration files, thereby breaking the server functionality. I want the client to be able to modify configuration settings without messing up the ones on the server. The not so elegant solution was to take a copy of /etc and export that separately. Once the network client booted up, it will have to mount the client's version of /etc over NFS on top of the existing /etc thus masking it. Confused? Don't worry, lets move on.
- Create a directory to hold the client's copy of /etc and take a copy of existing /etc
sudo mkdir /nfsroot
cp -a /etc /nfsroot
- Edit NFS's /etc/exports file to export your full root (/) as well as client's version of /etc
/ 192.168.2.0/24(rw,no_root_squash,async,no_subtree_check)
/nfsroot/etc 192.168.2.0/24(rw,no_root_squash,async,no_subtree_check)
- Sync your exports
exportfs -rv
6. Client related configuration
We need to adjust the /etc/fstab and network configuration files (/etc/network/interfaces) of the client so it does not try to mount the standard root or refresh it's IP address (as we have already offered that early on during the boot process over DHCP).
a. Edit /nfsroot/etc/fstab
proc /proc proc defaults 0 0
192.168.2.1:/ / nfs defaults 1 1
b. Edit /nfsroot/etc/network/interfaces
auto lo
iface lo inet loopback
iface eth0 inet manual
Place this custom init script to runlevel 5 (where the client will boot to) to have the client mount our alternative /etc over NFS.
Create /etc/rc5.d/S01netclient
#! /bin/sh
if cat /proc/cmdline|grep -q '/dev/nfs';then
# Mount network client friendly etc
mount -t nfs 192.168.2.1:/nfsroot/etc /etc
fi
Finally grant it execute permission.
chmod +x /etc/rc5.d/S01netclient
Testing it all out
Unfortunately having done all this, it doesn't quite boot as I'd expected and had to settled. The problem seems to be that /etc doesn't get mounted over NFS fast enough and so ends up using the server's /etc. The problem has to do with the network file where its using the server's network configuration file.
I have not go around to doing a clean fix but for now handle this using a custom shell script.
Create a script called /etc/init.d/netboot
case "$1" in
start)
echo 'Starting NetBoot services...'
iptables -F
ifconfig eth0 192.168.2.1
cp -f /nfsroot/etc/network/interfaces /etc/network
/etc/init.d/dhcp3-server restart
/etc/init.d/portmap start
/etc/init.d/nfs-kernel-server start
/etc/init.d/tftpd-hpa start
;;
stop)
echo 'Stopping NetBoot services...'
/etc/init.d/tftpd-hpa stop
/etc/init.d/nfs-kernel-server stop
/etc/init.d/portmap stop
/etc/init.d/dhcp3-server stop
cp -f /etc/network/interfaces.orig /etc/network/interfaces
;;
*)
echo 'Usage: $0 {start|stop}'
exit 1
;;
esac
Grant execute permission to the script
chmod +x /etc/init.d/netboot
Basically when you call the script with start, we manually setup the IP address of the interface eth0 of the server and clear any default firewall rules (iptables -F), that may prevent DHCP/TFTP/NFS from working. Then we copy the interfaces file, overwriting the exisitng /etc/interface file.
When you stop the service, we restore the network interfaces file using a backup. So the final step before you test is to take a backup of the interfaces file.
sudo cp -a /etc/network/interfaces /etc/network/interfaces.orig
When your ready, run the script and once your done don't forget to re-run the script with stop or your server's network will be down the next time it boots :)
sudo /etc/init.d/netboot start
Then power on your client computer and get it to boot off the LAN while you cross your fingers.
If you come across any problems, you can try to debug by change the default runlevel to Single user mode by replacing the APPEND line in /tftpboot/pxelinux.cfg/default:
APPEND root=/dev/nfs initrd=initrd.img nfsroot=192.168.2.1:/ ip=dhcp rw single

Conclusion
We looked at how we can get an Ubuntu OS running on a server to boot over the network on to diskless client. Obviously a lot more work is needed to improve its security and make it work more seemlessly. I'd like to hear <via bud@thinkcube.com> of your experience testing this out on different machines and any improvement ideas you have.
Reference
DisklessUbuntuHowto - https://help.ubuntu.com/community/DisklessUbuntuHowto
gPXE (PXE booting for computers can't PXE boot) - http://etherboot.org/wiki/howtos
by
Post new comment