Rolling your own Linux Live System from scratch Part 2
Initramfs
An initial RAM file system is a mini root filesystem zipped up into a compressed archive. It is loaded by the kernel at boot time and its purpose is to prepare the real root filesystem for use.
An initramfs is useful for situations where extra kernel modules most be loaded, or a hard disk partition must be decrypted before the real root filesystem is usable. In our case we want to mount the root filesystem in RAM, and union mount it with tmpfs so we can make non-permanent changes to it.
We start by building a skeleton of the directories our initramfs needs.
Busybox contains all the common userspace tools we’ll need to prepare our root filesystem. Your favorite distribution’s package manager may have a static version of Busybox, otherwise compile one yourself. If you have a Gentoo system, then emerging with the static
USE flag will also do the trick. The reason we want a static version is so we can drop the Busybox binary into the work/initramfs/bin/
directory and not worry about also including any dynamic libraries it might need, including libc
.
To check if a binary is static or not, run the file
or ldd
commands on it.
Init
Our initramfs needs an init process to do its job. Though when we thing of init daemons we tend to think of behamoths such as Systemd and OpenRC in reality they can be as simple as a single shell script.
Be warned however, Bash is way too big to squeeze inside Busybox; what we will be working with is called Ash. It is similar enough to Dash that we can use their documentation.
Below is a minimal init script which will do some basic setup and then drop you into an interactive shell.
Generating the Archive
The initamfs must be in a specific format in order for the kernel to recognise it.
Testing
Now it is simply a matter of copying it to the boot partition and making adjustments to grub. Under grub legacy, the following addition to /boot/grub/grub.conf
will allow us to test our new live system.
However, testing on bare metal involves waiting for a physical machine to boot and moving USB drives around and can be unnecessarily time consuming. An alternative could be to test inside a virtual machine instead.
Below is an example Xen configuration.
As an added sneaky trick, we can attach our squashfs root file system image to the virtual machine by pretending it is some kind of read only virtual harddrive. This also works under Qemu-KVM, however in this case it may to necessary to tell Qemu that the squashfs image is a DVD.
A Note on Keymaps
Like most people, if you’re not from the U.S. you will probably find a localized keymap useful, especially if you plan to type in passwords. Fortunately this is a simple process. Busybox conatins two applets called dumpkmap
and loadkmap
we we can use to generate a special file describing our system’s current keyboard layout and later load that file when our initramfs runs.
To generate the keymap file, run the following commands on a machine with the desired keyboard layout.
In the init
script, add the following lines to load the keymap again.
Finishing up
So far we have an initramfs which will dump us into an interactive shell session. This is useful because it will allow us to manually run the commands we would like and gain immediate feedback on any problems.
First we need to figure out where the squashfs image is. If we’re running this from a USB drive on bare metal then we need to mount the USB drive (something like /dev/sdb1
). If we’re running virtualised and added the squashfs image itself as a virtual block device (something like /dev/xvda
) then we can treat that /dev/
block device as the squashfs image file itself.
or an Xen based example
In the previous post we saw how to union mount the squashfs image.
If everything went well then /un
should now contain what appears to be a read write copy of your root filesystem image except any changes will not persist after power down.
The final thing to do is to switch_root
and “boot into” the new root filesystem.
Once you’ve got this process working manually it is simply a matter of adding the commands to the init script. One final note: if you’d prefer the rootfilesystem image to be entirely resident in RAM (i.e. you’d like to pull the USB drive out of the machine after it has finished booting), this is simply a matter of cp
ing the squashfs image from the USB drive before mounting it.
Finding the Squashfs Image
One final, final note. If you have a stable environment i.e. you’re not plugging and unplugging USB drives or internal storage devices left right and centre then you can probably get away with hardcoding something like /dev/sdb1
into the init script.
However, a more robust approach would be to identify the device based on its UUID.
Running the blkid
utility (may require root) will display a list of block devices and their Unique Universal IDentifier.
With a little sed
it is possible to extract the /dev/sdX
portion of the blkid output.
Note the use of POSIX style regular expression syntax, this is because Busybox does not support sensible alternative flavours in order to keep its size small.