PXE boot Ubuntu from a Debian server

From nikosapi.org wiki
Revision as of 11:59, 24 April 2011 by Nikosapi (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

External Links