Q: What does this doc do?
A: Saves you a bit of headache trying to get an initramfs built that will boot your encrypted root volume
Q: There's already plenty of doc, why bother?
A: This isn't a wholesale substitute for any of the existing documentation. However what I've found in the existing documentation is that you either find excessive information, that tries to solve every potential esoteric case a user might come across, and in the process making it a tad confusing and overwhelming for the 99% of users who just want a fairly simplistic setup. There are a dozen docs, some just on initramfs in general, some on luks/dm-crypt, some on lvm+dm-crypt+luks, all of which have a different way of doing things, all of which provide different examples, never really bothering to stop and give a simple example, or explain why something was done in a particular way in their example.
Q: Can I skip the other docs and just read this?
A: Maybe. Probably not. You should be somewhat familiar with the basics of cryptsetup (e.g. you need to know how to luksOpen, and if you haven't done so already, luksFormat - those aren't covered here), know how to mount things. Basically, after you've read all of the other doc and sat there banging your head trying to figure out how to modify their examples, failed, tried using some automated tool, failed, and are sick of it all, you probably have enough base knowledge to pick this up easily. Probably the best way to use this doc, is to go through the handbook, partition your disks, go through the bits of dm-crypt+luks doc, get your encrypted volumes (including root) formatted and set up, read through the Gentoo Initramfs wiki, see how much of it you can get your head around, then keep this page open in one tab, the Initramfs page open in another.
Automated Tools: There are a ton of automated tools out there which will supposedly do all of the initramfs creation for you.
Documentation: As is the case with the 'tools' that are supposed to make this automatic, there are loads of pieces of documentation that, if you piece them together, have a huge chunk of useful information, but none of them are really straightforward enough or organized enough to give you a functional end result. They may be written for an audience beyond your (and certainly my) level of comfort and knowledge, they may have poorly documented examples or none whatsoever, or a combination of all of these. Either way, no single document gave me the information I need in a clear, concise, easy-to-parse format or manner rather. This is not to rant and rave and complain about the documentation, really, never blame the tool for your inability to understand the tool, but at the same time if you can't figure out how to use the tool, it's not particularly useful to you now is it.
In case it hasn't been made abundantly clear already, this is NOT a wholesale replacement for at least a vague familiarity with encrypted volumes in general, nor will reading this along be a sufficient replacement for the other existing wikis should you wish to do anything more complex than have a standard root volume, encrypted with a passphrase provided at boot time. This doesn't cover off using key files, or dmcrypt setup - there's a wiki and plenty of doc for once you've at least gotten your system to unlock and mount root, and well, start itself up.
You should understand what 'mount' means to use this, you should have an idea of device nodes (for example, you need to know if your root partition is sda1, sda2, sda3, whatever). You should have already done a luksFormat of root, made a file system, mounted it, and all of that. You should know how to configure a custom kernel that works with your hardware, what file systems you need, and so forth. This document doesn't explain how to configure your kernel to support dm-crypt, how to enable initrd support, and what have you. This is already covered in detail within the Gentoo Initramfs Wiki Page.
If you already know how to set up encrypted volumes, know how to mount things, configure a kernel, and have a general understanding of the existing docs for this sort of thing, you should be fine. If you've tried getting this working multiple times, and failed, you should be just fine as you'll have picked up enough in your failed attempts to know how to manage here.
Before you get started actually hammering away at your keyboard typing commands, it's probably useful to point out in general how an initramfs is laid out, and give a crude explanation of how things interact. I may be technically wrong on some of these explanations, but aside from being wrong bruising my ego, it shouldn't have any negative effect on the outcome of you following this guide - things should still work for you.
Generally speaking, an initramfs is going to contain a small, minimalist rather, directory structure with a few key binaries and device nodes, which are utilized within a script named 'init' which will be located at the root of this directory structure. Basically, when you boot up your kernel, if you tell your kernel to use an initramfs (specified with the initrd= parameter in grub.conf), it will unpack this miniature directory structure and all of its binaries into memory, then execute '/init', which will make use of these binaries and device nodes to do things like, in our case, run cryptsetup to unlock your root volume, do the initial read-only mount of your root volume so that its contents can be read and processed, and go through the on-disk startup routine.
Think of it along the lines of someone making a very very minimal linux distro that contains the bare minimum number of directories for all of the small few programs it needs to run, contains just the one or two programs, as well as any files they depend on such as device nodes (e.g. /dev/tty, /dev/console, /dev/urandom)
Continuing with this example, say all that you want this minimalist Linux distribution to do, every time, is cat the contents of a file named /hello.txt to the console whenever the system starts up. So what do you do? You make the character device /dev/console, copy over cat, copy over any files cat needs, and write a script that will run every time this minimalist Linux distro loads, which will 'cat /hello.txt'. Now, to make it portable, you decide to tar up this entire minimalist Linux distro into an archive. Really this is no different from how an initramfs functions.
In the case of an initramfs, the kernel will unpack the initramfs archive, and by default, it will automatically look for an executable script inside the archive at the root named 'init'. You could of course name it 'ralph', but then you'd have to put 'init=/ralph' within grub.conf to override the default name of 'init'.
Now in order for all of the commands in 'init' to be successful, for the ones that require certain device nodes, those device nodes need to be present. For example, cryptsetup may need /dev/urandom, so that has to be there. If you don't do a static cryptsetup binary, you need to copy all of the libraries it's linked against into this file system at whichever place cryptsetup expects them. To that same end, one common point of confusion, is that when writing 'init' and telling it what to do, the paths specified inside 'init' are relative to your initramfs directory structure, and not the structure of what you have installed on your hard disk! So even if your hard disk has a /dev/sda1, for example, if there's no device node for /dev/sda1 inside your initramfs' directory structure, you can't write any commands into 'init' that depend on /dev/sda1, as the initramfs doesn't even know about your hard disk at this point (well, it does, but pretend it doesn't for our purposes here).
Following this is an example directory structure for an initramfs. Again, think of it as a minimalist Linux distribution, unpacked to ram, used to do a few small tasks, then discarded. Full steps for making the directory structure, copying over files, and so forth, can be found later on this document. So let's look at this example directory structure - the paths should look familiar if you read the Gentoo Initramfs wiki page:
$ pwd /usr/src/initramfs [email protected] /usr/src/initramfs $ find . |xargs file .: directory ./sbin: directory ./sbin/cryptsetup: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.9, stripped ./bin: directory ./bin/busybox: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.9, stripped ./mnt: directory ./mnt/root: directory ./dev: directory ./root: directory ./etc: directory ./lib: directory ./init: a /bin/busybox sh script text executable ./proc: directory ./sys: directory
[email protected] /usr/src/initramfs $ find . |xargs file .: directory ./sbin: directory ./sbin/cryptsetup: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.9, stripped ./bin: directory ./bin/busybox: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, for GNU/Linux 2.6.9, stripped ./mnt: directory ./mnt/root: directory ./dev: directory ./dev/sda1: block special ./dev/sda2: block special ./dev/null: character special ./dev/tty: character special ./dev/urandom: character special ./dev/random: character special ./dev/console: character special ./root: directory ./etc: directory ./lib: directory ./init: a /bin/busybox sh script text executable ./proc: directory ./sys: directory
If you look at the directory listing output above, you will note it is made up of five different things
So by this point, you're probably tired of reading fluff. Or did you even read the fluff? Forget the fluff, just give me the commands to type dammit! Since you're twisting my arm, I suppose I can accommodate. If you just skimmed through the rest of this doc, or just skipped over every other section, this is the section you need to pay attention to, especially when it comes to discussions on making the 'init' file/script.
Before we can begin copying over files, we need to set up the directory structure. You can use the same directory structure detailed in the Initramfs wiki, there's nothing new in here that isn't covered there, but in case you don't have that open in another tab, I include it below. You don't have to do this on the machine you're configuring - I did this on my laptop, bundled it up, copied it to my thumb drive, moved it to the new system where I'm setting this up - it doesn't matter where you're doing this, so long as you can bundle it up correctly (instructions to follow in a few!) and move it to /boot. And remember, as mentioned before, once the initramfs is loaded, all paths are relative to the root of the initramfs, so it doesn't matter what you call the directory where you start your work on making all of these directories; you're just going to cd to it later, and end up packaging everything up relative to the root of that anyway:
mkdir /usr/src/initramfs cd /usr/src/initramfs mkdir /usr/src/initramfs/bin mkdir /usr/src/initramfs/lib mkdir /usr/src/initramfs/dev mkdir /usr/src/initramfs/etc mkdir -p /usr/src/initramfs/mnt/root mkdir /usr/src/initramfs/proc mkdir /usr/src/initramfs/root mkdir /usr/src/initramfs/sbin mkdir /usr/src/initramfs/sys
NOTE: If you compiled your kernel with devtmpfs support, you can skip this section. These character devices will be created by init when you mount the devtmpfs at /dev
Now we need to copy over the character devices things like cryptsetup and busybox are going to need. Note the -a switch applied to the 'cp' command. If you don't know why this is relevant, see 'man cp'. If you don't think this is relevant, do it anyway. If you forget this switch and your machine catches fire, don't come crying to me:
cp -a /dev/null /usr/src/initramfs/dev/ cp -a /dev/console /usr/src/initramfs/dev/ cp -a /dev/tty /usr/src/initramfs/dev/ cp -a /dev/random /usr/src/initramfs/dev/ cp -a /dev/urandom /usr/src/initramfs/dev/
NOTE: If you compiled your kernel with devtmpfs support, you can skip this section. These block devices will be created by init when you mount the devtmpfs at /dev
Before we can unlock the encrypted root, our initramfs is going to need somewhere to put it, so we need to copy over the block device that corresponds to our root partition. My root partition is /dev/sda2 (which gets unlocked via cryptsetup as /dev/mapper/root), so I'm copying over /dev/sda2 to the directory where I have all of the other initramfs files. I actually copied over sda1 first, because when I was partitioning this thing, I wasn't sure if I wanted root to be sda1, or sda2, so I copied both, figuring my initramfs should work either way (assuming I write my 'init' correctly). Again, note the switch supplied to 'cp', as well note you don't have to do both, only the one that corresponds to your root partition - I show both, because I typed both:
cp -a /dev/sda1 /usr/src/initramfs/dev/ cp -a /dev/sda2 /usr/src/initramfs/dev/
At this point you should have all of the directories and screwy special devices under /dev that your binaries are going to need, so you can begin copying those over. Busybox will provide 'mount', and a basic shell, cryptsetup will provide, well, cryptsetup, used for unlocking the volume and asking you for a password:
cp -a /bin/busybox /usr/src/initramfs/bin/busybox cp -a /sbin/cryptsetup /usr/src/initramfs/sbin/cryptsetup
So now we have all of the tools, files, directories, binaries, that we need in order to get the root volume unlocked and mounted. All that's left is fashioning a script that will run these tools and binaries in the correct order to get things unlocked and mounted. This should be easy enough if you have a gander at the example below. By default, the kernel looks for a file named 'init' to execute - init is the glue that pieces all of these binaries and commands and everything else together. Its creation is probably the biggest stumbling block I personally hit, and the main reason for my writing this document - it takes far less to have a functional init than the other documentation tells you, and this contains no fancy shell syntax, just a handful of 'mount' commands, plus one reference to cryptsetup. The script is heavily commented, so I won't editorialize too much before and after:
#!/bin/busybox sh # dropping to a rescue shell lets you attempt to mount, cryptsetup, etc, by # hand at least. Below, I call the rescue_shell function if mounting root fails. # It must be defined prior to its call, so we do it up top. rescue_shell() { echo "Something went wrong. Dropping you to a shell." busybox --install -s exec /bin/sh } # temporarily mount proc and sys mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs none /dev #only do this if you've built devtmpfs support into your kernel #do your stuff here, e.g. lvm, cryptsetup, whatever # [crypt] # adjust 'sda2' below to match your root device. # the below makes the devmapper file /dev/mapper/root. If you used # "crypt-root" as your name, change the last string 'root' to 'crypt-root' # this command should be fairly familiar, as you will have run it when you # initially set up the crypto on your disk. cryptsetup -T 5 luksOpen /dev/sda2 root # mount root fs read only on /mnt/root, one of the directories in the initramfs, which you should have # created if you followed this guide, or fail back to busybox shell so you can at least # attempt to do some of this stuff manually. mount -o ro /dev/mapper/root /mnt/root || rescue_shell #clean up. The init process will remount proc sys and dev later umount /proc umount /sys umount /dev # boot and do switch_root nonsense. Similar to a chroot I suppose, actually this # whole process is similar to mounting things and chrooting for a gentoo base install, # only in this case it's a script inside your initramfs doing it - not exactly, but close enough exec switch_root /mnt/root /sbin/init
The above init and initramfs structure give you a very basic set of functionality, but hopefully do so in a way that, should your needs for an initramfs be different (e.g. creating one for lvm or raid) you can do so with minimal modification. There are two main pieces of this that you may want to modify (still excluding suspend and hibernate for the time being):
The heavy lifting is done. We've done all of the bits where you actually have to use your brain. Now, all you have to do is bundle up all of these files and directories into a cpio archive that the kernel can understand, gzip it, move it over to boot, pass it on the kernel command line via grub.conf. This is easy enough to do, and the steps are covered in other documents. You can read more about bundling it on the Gentoo wiki. I've copied these commands from there, and you may have to emerge a handful of packages in order to get the binaries needed to make a cpio archive - again, this is already covered on the initramfs wiki.
cd /usr/src/initramfs/ find . -print0 | cpio --null -ov --format=newc | gzip -9 > /boot/initramfs.cpio.gz
title Gentoo (2.6.36-zen2) root (hd0,0) kernel /kernel-zen initrd /initramfs.cpio.gz
Questions? Comments? I mean, I hope this is helpful and all, but there's a reason I haven't left any contact details here. Enjoy!