Creative Commons

2007-10-19 13:13:59

Create the Über-LiveCD

So yesterday was the day. Finally the extremely custom LiveCD was in a perfect working condition. Now, if you're expecting this CD to cure cancer or do your homework for you, you're out of luck. You could probably use this CD to help you do the research to cure cancer and the research for your homework, but that's another thing entirely. Actually, forget I said any of that. There is no warranty of any sort with this CD, explicit or implied. YMMV.
Let's go over the requirements for this CD right off the bat.
So there are our basic requirements. Let's dig in.


The first step was to choose our distribution. We are Fedora users. We started with RedHat and then moved to Fedora once RedHat went "pay". However, we use Knoppix as our default rescue environment. So we wanted to keep it in this arena. We immediately found Revisor. Revisor, the successor to Kadischi, is a Python GUI frontend to the livecd-tools package. It utilizes kickstart, a configuration management solution for Linux distributions, to allow the user to customize the LiveCD's root password, installed packages, and numerous other options.
After attempting to create a very basic custom CD using Revisor, we realized that Revisor is pretty sucky. We had done almost every customization that Revisor allows us to make, however none of them were applied to the final CD. The root password wasn't set correctly, there were tons of packages installed that we didn't pick, and other, very frustrating, items. But, instead of ditching Revisor, we kept it for two reasons:


The second point is where we'll go next. Fedora comes with the default kickstart creator, system-config-kickstart. This application lets us make a kickstart script with all of the customization we need. So we used system-config-kickstart to create a kickstart file that sets the root password, installs only the packages we want, disables the firewall, SELinux, and the network, and lots of other things. What are those "lots of other things?" Well, let's look at [most] of the kickstart file. You can download the full file here.
auth --useshadow --enablemd5 graphical firewall --disabled firstboot --disable keyboard us lang en_US rootpw --iscrypted $1$inxs4MNP$.mhX/DpHmNWGQ.KUgvuuj/ selinux --disabled install cdrom reboot timezone --isUtc America/New_York xconfig --defaultdesktop=GNOME --depth=16 --resolution=1024x768 --startxonboot bootloader --location=mbr zerombr clearpart --all --initlabel %post /usr/sbin/useradd -d /home/train -c "Train" -g 20 train /bin/echo "train" | /usr/bin/passwd --stdin train /bin/echo -e "[daemon]\nAutomaticLoginEnable=true\nAutomaticLogin=train" > /etc/gdm/custom.conf /bin/echo -e "Section \"ServerFlags\"\nOption \"DontZap\" \"yes\"\nEndSection" >> /etc/X11/xorg.conf /bin/sed -i 's/^ca/#ca/' /etc/inittab /bin/sed -i 's/^[1-6]:/#/' /etc/inittab /bin/echo "exec /usr/bin/twm" > /etc/X11/xinit/Xclients /bin/echo "/usr/bin/twm" > /etc/X11/xinit/xinitrc /bin/echo -e "/usr/bin/mytrainapp/mytrain &\nexec /usr/bin/twm" > /home/train/.xsession /bin/chmod 4755 /sbin/shutdown /sbin/chkconfig bluetooth off /sbin/chkconfig cups off /sbin/chkconfig firstboot off /sbin/chkconfig ip6tables off /sbin/chkconfig iptables off /sbin/chkconfig network off /sbin/chkconfig nfslock off /sbin/chkconfig ntpd off /sbin/chkconfig sendmail off /sbin/chkconfig sshd off /sbin/chkconfig yum-updatesd off %packages @admin-tools @editors @base . . .
So let's take a closer look. The first section is normal kickstart stuff, configuring the base OS. The root password, by the way, is "password", so don't think you're going to discover my super-secret password by decrypting that.
What we're really interested in is the %post section. This is the part of the kickstart file where you can enter your own commands. So what did we do?
/usr/sbin/useradd -d /home/train -c "Train" -g 20 train
This creates our normal user that will run our custom training application.
/bin/echo "train" | /usr/bin/passwd --stdin train
This sets the password for our user to "train".
/bin/echo -e "[daemon]\nAutomaticLoginEnable=true\nAutomaticLogin=train" > /etc/gdm/custom.conf
This edits the GDM (Gnome Display Manager) configuration so that it automatically logs in our new user.
/bin/echo -e "Section \"ServerFlags\"\nOption \"DontZap\" \"yes\"\nEndSection" >> /etc/X11/xorg.conf
This disables the ability to kill the X server by using the CTRL+ALT+BKSP combination.
/bin/sed -i 's/^ca/#ca/' /etc/inittab
This disables the ability to reboot the machine using the CTRL+ALT+DEL combination.
/bin/sed -i 's/^[1-6]:/#/' /etc/inittab
This disables all of the virtual consoles (CTRL+ALT+F{1-6}) so that the only active getty is our X session.
/bin/echo "exec /usr/bin/twm" > /etc/X11/xinit/Xclients /bin/echo "/usr/bin/twm" > /etc/X11/xinit/xinitrc
These two items are for one reason only. Both files do multiple checks to see what WM is installed, and if nothing is, it fails to TWM (what we're using anyway) and opens an xterm and xclock. We don't want that stuff to run, so we wiped the files (> instead of >>) and only added back the line to run TWM.
/bin/echo -e "/usr/bin/mytrainapp/mytrain &\nexec /usr/bin/twm" > /home/train/.xsession
This makes it so once our user is logged in, our training application starts and TWM is run as our WM.
/bin/chmod 4755 /sbin/shutdown
Since the shutdown binary is already owned by root, we set the sticky bit (the 4 in the 4755) so that no matter who executes it, it will run with root priviliges, which is necessary for `shutdown` to be run.
The chkconfig lines turn off the services we won't want to start, but that isn't good enough, since we aren't sure that the chkconfig service won't screw them up. So later on, we'll make sure that the services are permanently disabled.
Other than that, the rest is the list of packages that will get installed. We chose the very least we could to get a functional X system.

Synergizing Kickstart and Revisor

Now that we have our custom kickstart file, we can open Revisor and tell it, on the "Load Kickstart Data" page, to use our custom kickstart file. It is important that you only check the "Use package manifest from kickstart data" checkbox. If you check the others, Revisor will attempt to make it's own kickstart file, invalidating all of the hard work you just went through.
Finish the steps and Revisor will create you an ISO file which can be burned to a CD. But we can't stop there. We're not even close to being done.

Finishing the Configuration

I mentioned above that we still need to permanently disable some services, in addition to adding our custom software. Since all we have now is an ISO file, we need to extract it's contents and do our thing.
First, we need to make some directories that we'll need.
> cd /var/live > mkdir isomount isofiles osmount
As you probably guesses from the folder names, we have some mounting to do. First, we need to mount the ISO file.
> mount -o loop /var/live/livecd-20071019.iso /var/live/isomount
An important note is that the iso9660 filesystem (the one used for CDs) is a read only filesystem. We need to copy the contents of our ISO file to another folder if we wish to edit them.
> cp -R /var/live/isomount/* /var/live/isofiles
Now we see that there are 2 folders and 1 file. The "isolinux" folder holds the files necessary to make our CD bootable, the sysroot folder is empty, and the squashfs.img file is an archive that is compressed using the squash filesystem. We need to unsquash this file, so we need to be able to manipulate squash filesystems.
Head on over to SourceForge and get the squashfs package. Then build and copy the binaries.
> tar xzf /var/live/squashfs3.2-r2.tar.gz > cd squashfs3.2-r2 > cd squashfs-tools > make > cp mksquashfs unsquashfs /usr/bin
Now that we have the ability to manipulate squash filesystems, we can unsquash our archive.
> unsquashfs -d /var/live/squashfiles /var/live/isofiles/squashfs.img
Do not create the "squashfiles" directory beforehand, as unsquashfs needs to make the destination directory itself. When we check out the contents of our squashfiles folder, we see an empty sysroot folder and an os.img file. This is the archive of our CD's filesystem.
> mount -o loop,rw /var/live/squashfiles/os.img /var/live/osmount
At last we see something useful. Now let's get to work.
First, let's get rid of those crummy services. Remember all of those services our kickstart turned off? You'll need to check the /etc/rc{1-5}.d directories and remove each startup file that matches the services you don't want to start. An example:
> cd /var/live/osmount/etc/rc2.d > rm -f S10network
Each file in the "rc" folders I mentioned are symbolic links to the real files located in /etc/init.d. Deleting them from the "rc" folders means they will not start at that runlevel, period. Be sure to delete the files only starting with an "S", as the ones starting with a "K" are the kill scripts. Those are always good to leave in place.
Now that the services are done, we need to inject our custom application.
> mkdir /var/live/osmount/usr/bin/mytrainapp > tar xzf mytrain.tar.gz -C /var/live/osmount/usr/bin/mytrainapp > chown -R 500:20 /var/live/osmount/usr/bin/mytrainapp
We have already checked the passwd file to see that our "train" user has an ID of 500 and the group file to see that it is in the games group (20). Do not be alarmed if you do an `ls -la` and see a different user owning those files. Remember, your system may have a different user with an ID of 500, but when the LiveCD boots, "train" will have an ID of 500. Everything will be ok.
The last configuration change to make is giving the user a right-click menu with two options, open the training application (if he accidentally closed it) and shutdown the machine. You'll have to make a .twmrc file in /var/live/osmount/home/train and fill it with these contents:
NoGrabServer RandomPlacement BorderWidth 1 TitleFont "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*" ResizeFont "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*" MenuFont "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*" IconFont "-adobe-helvetica-bold-r-normal--*-100-*-*-*-*-*-*" IconManagerFont "-adobe-helvetica-bold-r-normal--*-100-*-*-*" Color { BorderColor "slategrey" DefaultBackground "rgb:2/a/9" DefaultForeground "gray85" TitleBackground "rgb:2/a/9" TitleForeground "gray85" MenuBackground "rgb:2/a/9" MenuForeground "gray85" MenuBorderColor "slategrey" MenuTitleBackground "gray70" MenuTitleForeground "rgb:2/a/9" IconBackground "rgb:2/a/9" IconForeground "gray85" IconBorderColor "gray85" IconManagerBackground "rgb:2/a/9" IconManagerForeground "gray85" } MoveDelta 3 Function "move-or-lower" { f.move f.deltastop f.lower } Function "move-or-raise" { f.move f.deltastop f.raise } Function "move-or-iconify" { f.move f.deltastop f.iconify } Button1 = : root : "defops" Button1 = m : window|icon : f.function "move-or-lower" Button2 = m : window|icon : f.iconify Button3 = m : window|icon : f.function "move-or-raise" Button1 = : title : f.function "move-or-raise" Button2 = : title : f.raiselower Button1 = : icon : f.function "move-or-iconify" Button2 = : icon : f.iconify Button1 = : iconmgr : f.iconify Button2 = : iconmgr : f.iconify menu "defops" { "Trainign Menu" f.title "Training" f.exec "exec /usr/bin/mytrainapp/mytrain &" "" f.nop "Shutdown" f.exec "exec /sbin/shutdown -h now" }
Configuration done!

Rebuilding the CD

First step to recreating the CD is to unmount our filesystem.
> umount /var/live/osmount
Then we need to squash these files into a new squashfs.img. But first, we'll delete the old one so we don't get confused.
> rm -f /var/live/isofiles/squashfs.img > mksquashfs /var/live/squashfiles/* /var/live/isofiles/squashfs.img
The squashing takes forever. Once it's done we just need to repackage everything in the "isofiles" folder into our bootable CD. This should be able to be done with a very long mkisofs command:
> mkisofs -o /var/live/newcd.iso -b /var/live/isofiles/isolinux/isolinux.bin \ -c /var/live/isofiles/isolinux/ -no-emul-boot -boot-load-size 4 -boot-info-table \ -J -r -hide-rr-moved -V Training /var/live/isofiles
That didn't work for us (probably something stupid we're overlooking), but that doesn't matter. There is a very nice program to make the ISO for us.

Mastering the ISO

> yum install -y isomaster
Now that you have the ISOMaster program installed, we can open up our old ISO (since it already has the boot information) and just replace the squashfs.img file.
> isomaster /var/live/livecd-20071019.iso
The interface is a little unintuitive at first. The top section is your computer's filesystem and the bottom section contains the files in the ISO. Click on squashfs.img in the bottom section and remove it. Then, in the top section, find your squashfs.img in /var/live/isofiles and add it. All that's left is clicking File and Save As, giving it a new name, and voila!

Check the Libraries

Now that you have an ISO, you need to boot to it and make sure that the custom application will actually run. Depending on the libraries you used to build your application, it may or may not run. So first you need to boot to the ISO as if you had burned it to a CD and rebooted. For that, we'll use QEmu, which is installed by default in Fedora 7.
> qemu --cdrom /var/live/newcd.iso
Once you're booted, if your application doesn't automatically run, open an xterm (you do have a way to do that, right?). You may have to edit the .twmrc and remake the CD. But once you're in the xterm, `cd` to the directory and check to see if the live environment has the libraries your application needs.
> ldd /usr/bin/mytrainapp/mytrain
If it can't find certain libraries, you'll need to download them on your host machine, mount the os.img file, copy the libraries into /usr/lib in the os.img file, then go through the process of squashing and recreating the CD. Now that you've resolved the dependencies and your application runs, congratulations, you can now burn your very own customized LiveCD!



2007-11-20 17:19:31

James says...
Thanks for the writeup. I'll give this a shot today. What did you end up using for your super-slim pdf reader?

2007-11-20 19:05:49

slonkak says...
We used xpdf. It reads pdfs and not much else, which is exactly what we wanted.

2007-11-29 15:08:47

Norm says...
Perfect post! Thank you so much for the details. Everything

2007-11-29 15:42:52

slonkak says...
You're very welcome. I'm glad you found it useful.

2007-12-14 13:01:56

bithead says...
Capital bit of work. Thank!

2007-12-14 13:19:15

slonkak says...
Welcome! I hope it's working out for everyone.

2008-02-06 12:31:43

buzzdecafe says...
Excellent article. Can you please post the %packages list from your kickstart file? Or post the kickstart file for downloading? I'm having a little difficulty configuring a minimal X system, and I'd love to see how you did it. Thanks--

2008-02-06 13:06:12

slonkak says...
Sure thing. I've updated the article with a download link in the "Kickstart" section.

2008-11-17 13:13:21

Imad says...
The correct mkisofs command is (I found this in the live-cd tools in Fedora repositories)

mkisofs -J -r -hide-rr-moved -hide-joliet-trans-tbl -V <The volume name given in isolinux.cfg> -b isolinux/isolinux.bin -c isolinux/ -no-emul-boot -boot-info-table -boot-load-size 4 -o <output iso> <source dir>

2008-11-17 13:47:22

slonkak says...
Hmmm, it seems that the only addition to yours was "-hide-joliet-trans-tbl." I guess we did overlook that. Thanks for the info!

Post a comment!