The latest version of this document can be found at [1]. Background ========== We often use LiveCD (and particularly the Ubuntu one) for demonstrations during Free Software promotion events. However, the user experience is often quite bad, because LiveCD are slow, due to the poor speed of CD-ROM devices. As many of the computers we use in our meetings are connected through a 100 Mbit/s network, we had the idea of replacing the slow CD-ROM drive by a fast network connection. Briefly, what does the Ubuntu LiveCD is the following: - Boot a kernel - It loads an initrd as a ramdisk, which contains a basic system - It mounts this ramdisk as the root filesystem - It configures some basic devices on the machine, mainly to detect CD-ROM devices - Then executes some script to mount the CD-ROM, and then mount the casper/filesystem.cloop file of the CD-ROM (a compressed filesystem) as the new filesystem root. - And the show goes on. Our idea is simply to replace the mount of the CD-ROM by the mount of a NFS share (which is basically a copy of LiveCD). In order to do that, we need to tweak the initrd. These operations are described in the following section. The following work has been performed with an Ubuntu Breezy Live CD. The modifications and server operations have been made on a Debian Sid system. Adaptations might be needed for other versions. Quick start =========== 1) CD-ROM boot -------------- - Set up a server, as indicated in section "Setting up a server" - Download and burn the ISO available at [4] - Boot on the CD, type "ubuntu" to boot Ubuntu and "kubuntu" to boot Kubuntu 2) USB key boot --------------- - Set up a server, as indicated in section "Setting up a server" - Set up an USB key, as indicated in section "Testing using an USB key" - Boot ! ;-) Tuning the initrd ================= 1) Basic setup -------------- Create a working directory: $ mkdir mylive $ cd mylive From the LiveCD, copy install/vmlinuz and install/initrd.gz to your working direct. Supposing the LiveCD is mounted in /cdrom: $ cp /cdrom/install/vmlinuz /cdrom/install/initrd.gz . Uncompress the initrd: $ gunzip initrd.gz First of all, let's grow a little the size of the initrd so that we can install some more things inside it (supposing the original initrd weights around 13.20 Mb) : $ dd if=/dev/zero of=initrd bs=1M count=1 seek=15 $ /sbin/ext2resize initrd You now have access to the contents of the initrd, that we will modify in order to be able to mount the LiveCD CD-ROM through NFS. Mount it: $ mkdir initrd.dir $ sudo mount -o loop,rw initrd initrd.dir/ 2) Kernel tuning ---------------- Now, let's install the NFS and network drivers modules inside the initrd. These are fetched from the .udeb packages in the Ubuntu archive. We will suppose that the kernel inside of the initrd is 2.6.12-9-386. You can check it by looking in the lib/modules/ directory inside the initrd. Fetch the .udeb packages: $ wget http://archive.ubuntu.com/ubuntu/pool/main/l/linux-source-2.6.12/nfs-modules-2.6.12-9-386-di_2.6.12-9.23_i386.udeb $ wget http://archive.ubuntu.com/ubuntu/pool/main/l/linux-source-2.6.12/nic-modules-2.6.12-9-386-di_2.6.12-9.23_i386.udeb $ wget http://archive.ubuntu.com/ubuntu/pool/main/l/linux-source-2.6.12/nic-shared-modules-2.6.12-9-386-di_2.6.12-9.23_i386.udeb Create directories and uncompress them: $ mkdir nfs-modules $ cd nfs-modules $ ar xvf ../nfs-modules-2.6.12-9-386-di_2.6.12-9.23_i386.udeb $ cd .. $ mkdir nic-modules $ cd nic-modules $ ar xvf nic-modules-2.6.12-9-386-di_2.6.12-9.23_i386.udeb $ cd .. $ mkdir nic-shared-modules $ cd nic-shared-modules $ ar xvf nic-shared-modules-2.6.12-9-386-di_2.6.12-9.23_i386.udeb $ cd .. In each directory (nfs-modules, nic-modules and nic-shared-modules), you should have a control.tar.gz file, a data.tar.gz file and a debian-binary file. The data.tar.gz is the real contents of the package, and we will uncompress the 3 data.tar.gz at the root of the initrd: $ cd initrd.dir $ sudo tar xvzf ../nfs-modules/data.tar.gz $ sudo tar xvzf ../nic-modules/data.tar.gz $ sudo tar xvzf ../nic-shared-modules/data.tar.gz It has added more modules inside /lib/modules/2.6.12-9-386/, and they will allow to access the network and mount NFS shares. To allow the system to use these modules, we have to run "depmod" inside the initrd: $ sudo chroot . /bin/sh # depmod 2.6.12-9-386 # exit $ cd .. (You must specify the kernel version after depmod, otherwise, depmod will assume it's the kernel version of your host, not the kernel version of your initrd). 3) DHCP ------- Now, before mounting the NFS share, we need an IP and the simplest solution is to get it through DHCP. The LiveCD scripts already uses DHCP to get an IP, but they do it too late: after mounting the CD-ROM. As in your case, we need to access the network before mouting the fake CD-ROM, we'll do our own DHCP. To do so, we will compile a static binary of dhclient. We must do that because the dynamic version of dhclient (compiled out of the initrd, and then copied inside the initrd) doesn't work: # dhclient ... dhclient: relocation error: dhclient: symbol htons, version GLIBC_2.0 not defined in file libc.so.6 with link time reference So, let's go for a static dhclient: $ apt-get source dhcp $ cd dhcp-2.0pl5 Fetch the patch that modifies the compilation process of dhcp-client to generate a static binary, and apply it: $ wget http://thomas.enix.org/pub/livecd/dhcp-static.patch $ patch -p1 < dhcp-static.patch Also apply a needed Debian patch: $ patch -p1 < debian/patches/200_script.patch Configure, and compile: $ ./configure $ make The static binary is client/dhclient.static. Let's copy it inside the initrd, copy the dhclient script, and create the directory where dhclient stores its leases files: $ sudo cp client/dhclient.static ../initrd.dir/sbin/dhclient $ sudo cp client/scripts/linux ../initrd.dir/etc/dhclient-script $ sudo mkdir -p ../initrd.dir/var/state/dhcp/ $ cd ../ Create a dhclient.conf in the initrd: $ sudo vi initrd.dir/etc/dhclient.conf And add the following line to it: -------------------------->8--------------------------- request option-128, option-129; -------------------------->8--------------------------- 4) OpenSLP ---------- DHCP allows to get the IP, the gateway and other network parameters, but it also allows to get some custom parameters about the network configuration. We will use it to get the address of the NFS server providing the LiveCD. However, as there are places where you don't manage the DHCP server, we wanted to provide an alternative solution to find the NFS server automatically. We choosed to use the SLP, Service Location Protocol, a service discovery protocol standardized in RFC 2608. A free implementation is available, OpenSLP. The client part of OpenSLP is called slptool, and we will produce a static version of it for our initrd. $ apt-get openslp $ wget http://thomas.enix.org/pub/livecd/openslp-1.2.1-slptool-static.patch $ cd openslp-1.2.1 $ patch -p1 < ../openslp-1.2.1-slptool-static.patch $ automake-1.8 slptool/Makefile $ ./configure $ make $ sudo cp slptool/slptool_static ../initrd.dir/sbin/slptool 5) Booting process tuning ------------------------- Now, we need to patch the booting process of the LiveCD, by mounting an NFS share instead of the CD-ROM. To do that: $ wget http://thomas.enix.org/pub/livecd/cdrom-detect.patch $ cd initrd.dir $ patch -p0 < ../cdrom-detect.patch Now, upon boot, the initrd will get an IP through DHCP. Then, if a "nfs=" kernel parameter has been given, it will use it as the NFS share address (so it should be something like nfs=192.168.2.1:/livecd/). If no "nfs=" has been manually specified, it will try to automatically find the NFS share : o) First, using DHCP. If the kernel command line contains "ubuntu", it will look for an "option-128" configuration item from the DHCP lease. If available, it will use it as the NFS share address. If the kernel command line contains "kubuntu", it will look for an "option-129" configuration item from the DHCP lease. If available, it will use it as the NFS share address. If nor ubuntu neither kubuntu is specified, it will assume the user wants to boot Ubuntu by default. Informations concerning the configuration of the DHCP server are available in the "Setting up the server" section. o) Then, if the NFS share address has not been found through DHCP, it'll use the SLP protocol. It will ask for the service nfs-$DIST-livecd, where $DIST is ubuntu or kubuntu, as given on the kernel command line. If nor ubuntu neither kubuntu is available from the command line, then Ubuntu is assumed to be the choice. Informations concerning the configuration of the SLP server are available in the "Setting up the server" section. To sum up, there are three distinct methods to find the NFS share, in this order: from the kernel command line, from the DHCP lease, using the SLP protocol. (The idea of editing the cdrom-detect.posting script has been taken from [5]. The NFS mounting part has been inspired by [6]). 6) Configuration tuning ----------------------- Now, you need to add a preseed.cfg at the root of the initrd: $ vi preseed.cfg It must at least contain the following lines: d-i casper/enable boolean true d-i casper-udeb/snapshot/backing-file string /cdrom/casper/filesystem.cloop (On the original LiveCD, these options are passed on the kernel command line. But as the kernel command line length is limited, we prefer using a preseed.cfg configuration file.) We also recommend to add the following lines, that allows to automatically select the language, geographic location and keyboard mapping. With these configuration values, the LiveCD won't ask any question before booting under Gnome. Of course, you may need to adapt it to your language: -------------------------->8--------------------------- d-i countrychooser/shortlist select FR d-i kbd-chooser/method select fr d-i debian-installer/locale select fr d-i preseed/locale select fr_FR -------------------------->8--------------------------- (You can fetch a sample preseed.cfg file from http://thomas.enix.org/pub/livecd/preseed.cfg). 7) Finalization --------------- Now, we can unmount the initrd, and recompress it: $ sudo umount initrd.dir $ gzip -9 initrd Testing using an USB key ======================== Let's create a partition on the USB, of 10 Mo. Of course, you can use an already existing partition (ext2, ext3, vfat, whatever). $ sudo fdisk /dev/sda ... Format it and mount it: $ sudo mkfs.ext2 /dev/sda1 $ sudo mount /dev/sda1 /mnt/key/ Copy Grub files: $ sudo cp /boot/grub/stage1 /mnt/key $ sudo cp /boot/grub/stage2 /mnt/key Fetch the sample menu.lst file, customize it if needed, and copy it: $ wget http://thomas.enix.org/pub/livecd/menu.lst $ vi menu.lst ... $ sudo cp menu.lst /mnt/key Copy Initrd and kernel (either built from the previous section, or fetched at [2] and [3]) : $ sudo cp vmlinuz initrd.gz /mnt/key Unmount: $ sudo umount /mnt/key Install Grub on the USB key: $ sudo grub --no-floppy grub> device (hd0) /dev/sda grub> install (hd0,0)/stage1 (hd0) (hd0,0)/stage2 p (hd0,0)/menu.lst Creating a bootable CD-ROM ========================== Create a directory for the CD-ROM : $ mkdir livecdboot From the original Ubuntu Live CD, grab the files install/boot.cat, install/isolinux.bin and install/splash.rle: $ cp /cdrom/install/boot.cat livecdboot $ cp /cdrom/install/isolinux.bin livecdboot $ cp /cdrom/install/splash.rle livecdboot Then, copy the modified initrd, and the kernel: $ cp initrd.gz livecdboot $ cp vmlinuz livecdboot Then, fetch isolinux.cfg and isolinux.txt: $ wget http://thomas.enix.org/pub/livecd/isolinux.cfg $ wget http://thomas.enix.org/pub/livecd/isolinux.txt At this point, you can customize isolinux.cfg if needed, for example to set the correct language. Then, copy these to the directory created for the CD : $ cp isolinux.cfg livecdboot $ cp isolinux.txt livecdboot And create the ISO : $ mkisofs -r -V "Ubuntu Live CD over Network" -cache-inodes \ -J -l -b isolinux.bin -c boot.cat -no-emul-boot \ -boot-load-size 4 -boot-info-table \ -o livecdboot.iso livecdboot A sample result is available at [4]. Setting up the server ===================== 1) Set up the NFS server ------------------------ You simply need to copy the contents of the Ubuntu LiveCD (and/or KUbuntu LiveCD) to a directory on the server, and then export this directory (read-only is enough) through NFS. After mounting the Ubuntu LiveCD in /cdrom/ : $ sudo mkdir /mnt/livecd/ubuntu/ $ sudo cp -a /cdrom/* /mnt/livecd/ubuntu/ $ sudo cp -a /cdrom/.* /mnt/livecd/ubuntu/ After mounting the KUbuntu LiveCD in /cdrom/ : $ sudo mkdir /mnt/livecd/kubuntu/ $ sudo cp -a /cdrom/* /mnt/livecd/kubuntu/ $ sudo cp -a /cdrom/.* /mnt/livecd/kubuntu/ Then: $ sudo vi /etc/exports Add the line "/mnt/livecd/ *(ro)" $ sudo /etc/init.d/nfs-kernel-server restart 2) Set up the DHCP server ------------------------- We will not detail the complete configuration of the DHCP server, only the configuration of the option-128 and option-129 configuration items needed for the LiveCD. We assume that you're using DHCPv3. Simply add the following lines to your DHCP server configuration file (supposing that the NFS server is at 192.168.1.2) : -------------------------->8--------------------------- option nfs-ubuntu-livecd code 128 = text; option nfs-ubuntu-livecd "192.168.1.2:/mnt/livecd/ubuntu/"; option nfs-kubuntu-livecd code 129 = text; option nfs-kubuntu-livecd "192.168.1.2:/mnt/livecd/kubuntu/"; -------------------------->8--------------------------- If you can't modify the DHCP configuration, you may want to use the SLP protocol instead. 3) Set up the SLP server ------------------------ This is not needed if you have been able to modify the DHCP configuration by following the instruction of the previous section. First of all, install the OpenSLP server: $ sudo apt-get install slpd Then configure it by adding the following lines to the /etc/slp.reg file (supposing the NFS server is at 192.168.1.2) : -------------------------->8--------------------------- service:nfs-ubuntu-livecd:nfs://192.168.1.2:/mnt/livecd/ubuntu/,en,65535 description=NFS Server for LiveCD Ubuntu authors=toulibre service:nfs-kubuntu-livecd:nfs://192.168.1.2:/mnt/livecd/kubuntu/,en,65535 description=NFS Server for LiveCD Ubuntu authors=toulibre -------------------------->8--------------------------- And restart the server: $ sudo /etc/init.d/slpd restart Live CD customization ===================== Now that you use a single LiveCD image for all the workstations, I'm sure you'll want to customize it, for example to add more applications, better language support or whatever. This process is thouroughly explained at [7]. Problems and limitations ======================== This HOWTO is mainly a recipe for an hack, not a clean solution. It would be nicer to integrate this feature directly into the original Ubuntu LiveCDs. The first problem we see is that our solution does two DHCP requests: one before mounting the NFS filesystem, and one once it has been mounted. The first DHCP request is the one we added, which is mandatory to be able to mount the NFS filesystem. The second one is the one of the default LiveCD. In practice, this is not a real problem, because the second DHCP request should give the same IP as the first one, but it isn't really clean. Moreover, the first DHCP request performed by our modification is done in the background, and is not visible to the user. If no DHCP server answers the request, the user is never informed of the problem. Similarly, if the NFS mount doesn't work, the user is notified with a strange error message. Links ===== [1] English, http://thomas.enix.org/pub/livecd/HOWTO-Ubuntu-Live-Speedup [2] http://thomas.enix.org/pub/livecd/initrd.gz [3] http://thomas.enix.org/pub/livecd/vmlinuz [4] http://thomas.enix.org/pub/livecd/livecdboot.iso [5] French, http://forum.ubuntu-fr.org/viewtopic.php?pid=143333#p143333 [6] French, http://forum.hardware.fr/hardwarefr/OSAlternatifs/NFS-pivot_root-chroot-consors-sujet-49095-1.htm [7] English, https://wiki.ubuntu.com/LiveCDCustomizationHowTo Authors ======= Thomas Petazzoni - Gaël Utard -