PXE boot Ubuntu from a Debian server
This guide will help you set up a server from which you can boot diskless clients over the network. This is dissimilar from LTSP because all the processing gets done on the client side (aka "a fat client") instead of on the server. Here the server is only used as the client's root filesystem which means that you don't need a fancy server to support multiple clients (although the clients must have relatively modern hardware).
In this guide Debian will be running on the server and the clients will be booting Ubuntu 10.10.
Install Debian on the server
This is pretty straightforward, install from the "netinst" disk and select "Standard system" when asked what software to install.
Set up the Ubuntu chroot
In order to boot from Ubuntu on the client machine we need an Ubuntu userland somewhere on the server (I chose /opt/chroots). The reason why we have to download debootstrap is because the version included in the Debian repos doesn't contain the scripts necessary to install Ubuntu 10.10.
aptitude install binutils wget http://http.us.debian.org/debian/pool/main/d/debootstrap/debootstrap_1.0.29_all.deb dpkg -i debootstrap_1.0.29_all.deb mkdir -p /opt/chroots/ubuntu10.10 debootstrap --arch i386 maverick /opt/chroots/ubuntu10.10 http://archive.ubuntu.com/ubuntu/
Enter the Ubuntu chroot
Now we need to do a bit of configuration before this distro will be bootable. Firstly, enter the chroot:
chroot /opt/chroots/ubuntu10.10/
Run locale-gen to prevent annoying error messages from aptitude:
locale-gen en_CA.UTF-8 # change "en_CA.UTF-8" to your current locale
Make up a hostname to help differentiate the chroot from the server:
echo "ubuntuchroot" > /etc/hostname
Set up some dns servers (opendns is used in this example):
echo -e "nameserver 208.67.222.222\nnameserver 208.67.220.220" > /etc/resolv.conf
Set up a nice apt sources.list:
{ for distro in maverick maverick-updates maverick-security; do for type in deb deb-src; do echo -n "$type http://archive.ubuntu.com/ubuntu $distro " echo main restricted universe multiverse done done; } > /etc/apt/sources.list
That script should yield an /etc/apt/sources.list that looks something like this:
deb http://archive.ubuntu.com/ubuntu maverick main restricted universe multiverse deb-src http://archive.ubuntu.com/ubuntu maverick main restricted universe multiverse deb http://archive.ubuntu.com/ubuntu maverick-updates main restricted universe multiverse deb-src http://archive.ubuntu.com/ubuntu maverick-updates main restricted universe multiverse deb http://archive.ubuntu.com/ubuntu maverick-security main restricted universe multiverse deb-src http://archive.ubuntu.com/ubuntu maverick-security main restricted universe multiverse
Update your apt cache and install a kernel image:
aptitude update aptitude install linux-image-generic
Modify the initramfs config to support booting over NFS (change BOOT=local to BOOT=nfs):
sed -i 's/BOOT=local/BOOT=nfs/' /etc/initramfs-tools/initramfs.conf
Add the NFS root filesystem mountpoint to /etc/fstab (setting up the NFS server is described later on):
echo "NFS_SERVER_IP:/opt/chroots/ubuntu10.10 / nfs rw,noatime,nolock,vers=3 0 0" > /etc/fstab
Update the installed initramfs:
update-initramfs -ck all
Set a root password:
passwd # follow the prompts
Install and configure the TFTP server
The bootloader, kernel and initrd are transfered over TFTP, so naturally we have to set up a TFTP server. (Make sure you've exited the Ubuntu chroot at this point)
Install the TFTP server:
aptitude install tftpd-hpa
Make the base directory that tftpd will serve from:
mkdir /opt/tftpboot
Change the line in /etc/inetd.conf that looks like this:
tftp dgram udp wait root /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /var/lib/tftpboot
To this:
tftp dgram udp wait root /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /opt/tftpboot
And restart the inetd daemon:
/etc/init.d/openbsd-inetd restart
Install and configure PXELINUX
PXELINUX is a bootloader that works over PXE, we use it to boot the Ubuntu kernel over the network.
Install the PXELINUX image:
aptitude install syslinux-common
Copy over the bootloader:
cp /usr/lib/syslinux/pxelinux.0 /opt/tftpboot/
Make a boot directory and copy over the kernel and initrd images:
mkdir /opt/tftpboot/boot cp -L /opt/chroots/ubuntu10.10/initrd.img /opt/tftpboot/boot/ cp -L /opt/chroots/ubuntu10.10/vmlinuz /opt/tftpboot/boot/
Create a directory to hold the default PXELINUX config file:
mkdir /opt/tftpboot/pxelinux.cfg
Add the following to the PXELINUX config file, /opt/tftpboot/pxelinux.cfg/default:
default ubuntu-10.10 timeout 1 prompt 1 serial 0 9600 display display.msg label ubuntu-10.10 kernel boot/vmlinuz append initrd=boot/initrd.img root=/dev/nfs nfsroot=NFS_SERVER_IP:/opt/chroots/ubuntu10.10 ip=dhcp rw
Replace NFS_SERVER_IP with the IP address of the Debian server; hostnames are not allowed as dns isn't available that early in the boot process.
Create a file that will display various boot options to the user:
echo -e "\nBOOT OPTIONS\nubuntu-10.10" > /opt/tftpboot/display.msg
Here's what the directory structure looks like:
/opt: chroots/ tftpboot/ /opt/chroots: ubuntu10.10/ /opt/tftpboot: boot/ display.msg pxelinux.0 pxelinux.cfg/ /opt/tftpboot/boot: initrd.img vmlinuz /opt/tftpboot/pxelinux.cfg: default
Configure NFS
We use NFS to mount the root filesystem over the network, here's how to set it up.
Install the required packages:
aptitude install nfs-kernel-server nfs-server
Add something like the following to /etc/exports (eg. replace A.B.C with 192.168.0):
/opt/chroots/ A.B.C.0/255.255.255.0(rw,no_root_squash,no_subtree_check)
Export the NFS share(s):
exportfs -ra
Configure DHCP
In order for PXE to find a boot server it uses a special DHCP option. This is very easy to set up if you have a router running DD-WRT.
Go the following section:
Services->Services->Additional DNSMasq Options
Add the following string:
dhcp-boot=pxelinux.0,some-server,A.B.C.D
Where "some-server" is the hostname of the server and A.B.C.D is it's IP address.
You're done! Kinda...
At this point you should be able to boot off any computer that supports PXE booting. The next sections cover what to do once you're running on the client computer.
Installing a desktop environment
The bootstrapped version of Ubuntu that you're left with is very minimal, so let's install the standard Ubuntu desktop.
It's as easy as:
aptitude install ubuntu-desktop
This will take a long while because everything is being installed over the network (unless you're lucky enough to be using gigabit). It's important to install from the client because a lot of things won't install properly from the chroot on the server.
BOLD NOTE: After the installation completes the first thing you should do is disable NetworkManager. If you don't, NM has a bad habit of killing you network connection right before GDM starts which means you'll lose access to /.
Disable it like so:
update-rc.d -f NetworkManager remove
Optional: Add memtest86+ as a boot option
A PXE boot server is a great way to have access to utilities like memtest86+, here's how to set it up.
Note: This doesn't work, and I'm not sure why, see: http://forum.canardpc.com/showthread.php?t=28864
Install memtest86+ on the server:
aptitude install memtest86+
Copy over the memtest86+ binary:
cp /boot/memtest86+.bin /opt/tftpboot/boot/
Add the following to the bottom of /opt/tftpboot/pxelinux.cfg/default:
label memtest86 kernel boot/memtest86+.bin
Add the listing to display.msg:
echo memtest86 >> /opt/tftpboot/display.msg
TODO
This guide is far from complete. Here are things that still need to be done/added:
- Security considerations (nfs auth, etc)
- More comprehensive DHCP setup info