Some time ago, I've given my laptop yet another FreeBSD reinstall - mostly beause I wanted to encrypt its contents (hey, you never know!). It turns out the best way to do this is to use GEOM_ELI. Of course, I can't quite live without ZFS, so the idea was that I have a minimal /boot paritition and everything else lives on ZFS, which is encrypted using ELI.
In order to do this, I first performed a minimal 7.0-RELEASE install, using the following layout:
ad0s2a = 512MB = /
ad0s2b = 2GB = swap
ad0s2d = everything else = /X
Once installed, I rebooted. The idea is to move the install to the swap partition so I could turn ad0s2a into /boot. I used the commands below to do this:
# swapoff -a
# newfs /dev/ad0s2b
# mount /dev/ad0s2b /mnt
# cd /
# tar cf - --one-file-system * | tar xpf - -C /mnt
I edited /mnt/etc/fstab, so it would understand ad0s2b as /, and no swap or anything. Once that was done, I rebooted, and entered '0:ad(0,b)/boot/loader' (note the 'b' !) in the bootprompt, as I wanted to boot from the 'b' slice.
Once I was in my new install, I initialized my ELI encryption on ad0s2d and put a ZFS pool on it (note: the '-s 4096' means use a sector size of 4KB - this speeds ZFS up quite a lot - also, you do not need data authentication by means of '-a algo' as ZFS uses Merkle trees, which already perform the required authentication)
# geli init -b -v -s 4096 /dev/ad0s2b
# zpool create tank ad0s2b.eli
It's now time to create the new /boot and pollute it. Since the bootloader only understands /boot/..., we have to apply symlink magic to ensure our things like 'make installkernel' work correctly afterwards (/boot/... needs to go to ad0s1a:/boot/...)
# newfs /dev/ad0s2a
# mkdir /tank/bootdir
# mount /dev/ad0s2a /tank/bootdir
# cp -Rp /boot /tank/bootdir/
# ln -sf /tank/boot /tank/bootdir/boot
Note: ZFS needs a file '/boot/zfs/zpool.cache' if you attempt to boot from it. By the order of the commands above, it should be created before we are initializing the new /boot, but better make sure it is there or your system will not boot!
Now, edit /tank/boot/loader.conf and ensure it contains the following:
zfs_load="YES"
geom_eli_load="YES"
Note: on my laptop, I need 'hint.kbdmux.0.disabled=1' there as well - otherwise, the ELI password prompt misses keypresses. This appears to be a known issue.
We have to create /tank/bootdir/etc/fstab too, so the loader knows which filesystem to pass to the kernel; put the following in it:
tank / zfs rw 0 0
We have a working /boot now, so let's fill up the ZFS root:
# cd /
# tar cf - --one-file-system * | tar xpf - -C /tank
We need to update the fstab on the ZFS partion now, so edit /tank/etc/fstab and put the following into it (we can use ad0s1b as swap again once the system is rebooted):
tank / zfs rw 0 0
/dev/ad0s2a /bootdir ufs rw 1 1
/dev/ad0s2b swap swap sw 0 0
Final step is to prevent ZFS from re-mounting tank, as it will be used to root filesystem. This can be done by:
# zfs set mountpoint=legacy tank
The previous command probably will give an error regarding being unable to umount - this can be safely ignored.
Finally, reboot, and enjoy your uber-secure ELI-protected ZFS system! You'll probably want to fetch sources and build/install world/kernel, but I'll leave that up to you.
Closing words, I used to following guides to construct this post:
http://www.wanda25.de/geli.html on how to initialize ELI, and
http://wiki.freebsd.org/ZFSOnRoot on how to place / on ZFS.