Build Instructions

If you want to use features not yet included in the download version or you want to customize GuARD, you need to build it manually from svn. This guide will show you how.

I built GuARD based on this tutorial so there are a few similarities here.

Build Instructions

1. Requirements

Although the resulting disk image will fit on a single CD, the build environment will require around 4.5GB of disk space. Since you will have to compile all packages on your machine a stronger CPU will drastically reduce the build time.

Apart from that it is useful if you have some experience on the command-line since this entire tutorial uses the command-line, but it is no prerequisite.

If you have not already installed them, you will need to install cdrtools (contains mkisofs), subversion and squashfs-tools. In Gentoo you can achieve this by running the following command:

emerge app-cdr/cdrtools sys-fs/squashfs-tools dev-vcs/subversion

2. Setting up the build environment

The build environment consists of a main directory (here called “guard”) containing a build directory, which contains a directory for each supported architecture which each contain a source and a target directory. Thus the structure will look like this:

<main>/
  ↳build/
    ↳x86/
      ↳source/
      ↳target/
    ↳amd64/
      ↳source/
      ↳target/

The source directory will contain the actual build environment, we will later chroot into this directory and setup the entire system. The target directory will contain the files that will actually be on the final CD. Finally you will need the GuARD specific files, you can simply run this command inside the main directory:

svn co svn://svn.code.sf.net/p/guardlivecd/trunk /path/to/main/

If you already checked it out earlier you can update the svn directory by running the following command inside the directory:

svn update

Next you will need to set up the base system by downloading and extracting the latest stage3 tarball. For a list of Gentoo mirrors see http://www.gentoo.org/main/en/mirrors.xml.

You will need to select your architecture, since GuARD first supported x86, I will use x86 in this example (other architectures supported by Gentoo are: alpha, amd64, arm, ia64, mips, ppc, hppa and sparc; of these GuARD only supports amd64).

Since we will need the main directory of the build environment quite a lot it is useful to define its path as an environment variable. To name the directory, download and install everything you have to run

export GUARD="/path/to/main"
cd $GUARD/build/x86/source

wget -c -r --level=1 -nd -A .tar.bz2 \
  <yourfavoritemirror>/releases/x86/current-stage3/
  tar xvpjf stage3-*.tar.bz2
  rm stage3-*.tar.bz2

The last command will remove the tarball since it won’t be needed anymore.

We now have a core system, but it isn’t much more than a skeleton. To be able to install software we need a portage snapshot (portage is Gentoo’s package manager), you can download the latest snapshot from a Gentoo mirror of your choice:

cd $GUARD/build/x86/source/usr
wget <your favorite mirror>/snapshots/portage-latest.tar.bz2
tar xvjf portage-latest.tar.bz2
rm portage-latest.tar.bz2

Again, we can remove the archive, since we don’t need it anymore.

Now we need to move in all GuARD specific files. Theses files are in two separate trees: a generic tree and an arch specific tree. These files need to be copied into the stage3 installation. Currently it doesn’t matter if you move in the generic files first or second, still it’s best to move them in first since arch specific files should be able to overwrite generic ones. The best way to do this is the following:

cp -r $GUARD/generic/* $GUARD/build/x86/source
cp -r $GUARD/x86/* $GUARD/build/x86/source

3. Building Packages

The environment is ready, but now not a single package is installed. To do this, we first need to chroot into the source directory. In the chroot environment we need access to some pseudo filesystems, namely /proc, /dev and /sys. Before the chroot we will create and bind these directories:

cd $GUARD/build/x86/source
mount -o bind /dev dev
mount -o bind /sys sys
mount -o bind /proc proc

We will require internet access as well, so we can download the required packages. For this we need to copy /etc/resolv.conf.

cp /etc/resolv.conf etc/resolv.conf

Finally, we can chroot:

chroot . /bin/bash --login
# now we're in the chroot environment
env-update
passwd # set the root password, just in case

Note: If you are trying to build a 32bit disk on a 64bit system, you should use linux32 chroot instead of just chroot, so you have a 32bit chroot environment.

We do have the latest portage snapshot, still it might be a few days old. To be completely up to date run

emerge --sync

Now we can install packages. The GuARD files mark several packages as installed although they are not. You can install them in two steps:

emerge -e system

This will (re)install all system relevant packages like gcc or portage.

Note: You may want to edit /etc/make.conf. There is a line (currently commented out) that defines make options ("MAKEOPTS"), you should set these to -jX, where X is the number of cpu cores of your machine +1, so for a dual core this would be 3. This will make use of all cores and reduce build time.

You should then check if there was a gcc update (in most cases there will be during the initial setup)

gcc-config -l
# the output might look like this:
[1] i686-pc-linux-gnu-4.4.5 *
[2] i686-pc-linux-gnu-4.5.3

You should then select the most current profile, in this example it’s the second one, so you’d have to run

gcc-config 2
. /etc/profile

Before we can emerge everything else, we first need the kernel sources set up, since some packages require them to be in place.

emerge gentoo-sources

If you are updating GuARD, you will have to make sure you select the new kernel sources as well:

eselect kernel list
# the output may look like this:
[1] linux-3.1.7-gentoo *
[2] linux-3.2.0-gentoo

Similar to gcc-config select the latest version (in this case again number 2):

eselect kernel set 2

The kernel configuration is already included, we just need to put it in the right place and prepare it:

cd /usr/src/linux
cp /usr/src/kernel-config/.config .
cp /usr/src/kernel-config/modules.* .
yes "" | make oldconfig
make modules_prepare

Since oldconfig asks for user input on new kernel options, I use yes to set them all to the default value.

Now emerge everything else by running

emerge -e world

This will install all packages that are already marked as installed.

Both emerge commands will take quite a long time. It’s almost for sure that you will have to wait several hours for them to finish. You can split this time, though. For this simply press CTRL+C in the terminal running emerge, this will abort the merge. When you want to continue (even after a reboot and new chroot) just run

emerge --resume

You can now remove unneeded packages using

emerge --depclean

In most cases after each of these two commands you will receive a message telling that files in /etc need updating. All configuration related files are already the way they should be, so they don’t need updating. If you receive this message run the following before running any other commands:

rm /etc/conf.d/._*
etc-update
# a selection will be shown,
# choose "(-5 to auto-merge AND not use 'mv -i')"

This will remove the files that don’t need updating and update those that do.

All of this should take some time but afterwards all required packages are installed. If the compile process fails, you can try to find out why or file a bug.

Now it's time to setup the localization, for this simply run:

locale-gen

4. Building the Kernel

Next we need to build the kernel, the configuration is already included in the arch specific files and we already copied it. Building and installing the kernel comes down to

cd /usr/src/linux
make all
make modules_install
cp arch/x86/boot/bzImage /boot/vmlinuz

Note: even for amd64 the image is found in arch/x86/boot/bzImage.

In addition to the kernel we need an initial ramdisk, it can be built using genkernel

genkernel --no-ramdisk-modules --splash=guard initramfs
mv /boot/initramfs* /boot/initrd

This will build the initramfs and renames it to the name used in GuARD's grub config (already included in the generic files).

Unfortunately there is currently a bug in genkernel that breaks the regular boot mode, on top of it we need to include the aufs module. For this we need to extract the initrd using:

cd /usr/src/initrd
gzip -dc /boot/initrd | cpio -id

Now the initrd is extracted, now we need to include the necessary changes and the aufs module:

mkdir -p lib/modules/misc
cp /lib/modules/$(readlink /usr/src/linux | sed 's/linux-//')/misc/aufs.ko ./lib/modules/misc
cp -r ../initrd-additional/* .

The rather bulky expression within $(...) is used to select the right kernel version in case multiple kernel sources are present.

Now all we need to to is repack the initrd:

find ./ | cpio --quiet -H newc -o | gzip -9 -n > /boot/initrd

5. Start-up scripts

Before we can create the actual disk image, we first need to set the start-up scripts, this can be done with rc-update:

# remove unneeded scripts
rc-update del fsck boot
rc-update del hwclock boot
rc-update del modules boot
rc-update del netmount default
rc-update del swap boot
rc-update del localmount boot
rc-update del urandom boot
rc-update del savecache shutdown

# add new scripts
rc-update add eject-cd shutdown
rc-update add hwclock default
rc-update add syslog-ng default
rc-update add consolefont default

6. Cleaning up

All is ready to go, but the build environment contains huge amounts of stuff that are vital for the actual building process but are completely useless on the final CD and -- in fact -- will only waste space. Therefore we'll do some cleaning. Since we don't want to destroy our build environment, we will move all needed files to another place, this is where the target directory comes into play.

We will do some more aggressive cleaning in this section. For this we create a list of unneeded files from inside the chroot:

equery files --filter=obj,conf,doc,man,info gcc \
  | grep -v \.so\. > ~/USELESSFILELIST
equery files --filter=obj,conf,doc,man,info portage \
  | grep --invert env-update >> ~/USELESSFILELIST

for pkg in automake autoconf gentoolkit texinfo \
    flex bison gcc-config make m4 patch genkernel
do
  equery files --filter=obj,conf,doc,man,info \
    $pkg >> ~/USELESSFILELIST
done

First we need to unmount the bound directories, we don't want to copy anything that's within them, so we might es well unmount them

exit
# now we're out of the chroot again
umount $GUARD/build/x86/source/dev
umount $GUARD/build/x86/source/proc
umount $GUARD/build/x86/source/sys

We will use rsync to copy the data, this will benefit us when updating the CD, since rsync will only copy/remove the files that changed. In addition you can use the --exclude option to exclude unwanted files right away. The commands I use is a little bulky but contains everything you need:

cd $GUARD/build/x86
mkdir target/files
rsync --delete-after --archive --hard-links --quiet \
  --exclude="*/.svn" source/boot target
rsync --delete-after --archive --hard-links --exclude=/usr/share/man \
  --exclude=/usr/portage --exclude="/var/tmp/*" \
  --exclude="/var/cache/*" --exclude=/var/db \
  --exclude="/tmp/*" --exclude=/usr/share/doc \
  --exclude=/usr/src --exclude=/etc/portage \
  --exclude=/usr/local/portage --exclude=/usr/share/gtk-doc \
  --exclude="*.a" --exclude="*/.svn" --exclude=/root/USELESSFILELIST \
  source/ target/files/source

The first rsync copies the boot directory into what will be the CD root directory, this is needed since we will put everything else into a squashfs image. The second command copies everything with quite some exclusions. These exclusions come down to: "No temporary files, no documentation, no source codes, nothing that has to do with portage".

Afterwards exit the chroot and run

while read file; do
  file=target/files/source/$file
  [[ -e $file ]] && ( [[ -L $file ]] && rm $file || rm -r $file )
done < source/root/USELESSFILELIST

Here I used a few short forms to bypass some bulky "if..then..fi"-s, basically it checks if the file even exits (maybe it wasn't even copied). In case it does it checks if it's a link, since they behave a little different from other files. Afterwards the file is removed in the appropriate way.

Since the iso9660 filesystem does not support symbolic links and menu.lst in the boot directory is a symbolic link, we have to replace it:

cd $GUARD/build/x86/target/boot/grub/
rm menu.lst
cp grub.conf menu.lst

Now everything is clean, so we can continue to the final steps.

7. Building the CD image

We're almost there, all that's left to do is to pack the squashfs image and create the actual CD image.

cd $GUARD/build/x86/target/files
mksquashfs source $GUARD/build/x86/target/guard.squashfs
cd $GUARD/build/x86
touch target/livecd
mkisofs -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 \
  -R -boot-info-table -iso-level 4 -hide-rr-moved -c boot.catalog \
  -o $GUARD/build/x86/guard-x86.iso -V "GuARD (x86)" -x files target

This will first create the squashfs image and afterwards the CD image in $GUARD/build/x86/guard-x86.iso. In addition a file named "livecd" is created in the CD root. This is needed so the CD can be detected during boot.

All done! Now all you need to do is burn it and use it. Of course you may want to test the image first without wasting a blank CD. For this you can use a virtual machine like qemu or VirtualBox.

A. Updating the Disk

Updating is actually quite simple: Copy the latest generic and arch specific files into the working directory, next chroot into it and run

emerge --sync
emerge -uDN system
emerge -uDN world
emerge --depclean
etc-update

If new kernel sources were installed rebuild the kernel (you can keep the initrd), otherwise just exit the chroot and rebuild the image. Once outside the chroot, simply continue from Cleaning up. With one exception: you need to delete the old squashfs image.

rm $GUARD/build/x86/target/guard.squashfs