Encrypted ZFS Root (bsdinstall, 9.X+)

I wanted to set up a ZFS mirror for my root filesystem, but I also wanted it to be fully encrypted. Unfortunately, as of the time of this post, we don't have native ZFS encryption. For now, we have to use ZFS on top of Geli. There's a bit of overhead using the two together, but it's not bad, especially if you have a CPU with AESNI. Most of the guides I found online were outdated (using sysinstall, written for FreeBSD 7, etc) so I decided to write my own.

This process consists of:
  • Installing the OS normally to a small partition/drive
  • Booting into that to set up encryption and your zpool
  • Moving things over to this new filesystem
  • Removing the initial files
At the end, you should have a fully encrypted ZFS setup with a flash drive used to boot the system.

In my case, I have one 2GB flash drive (which would normally be da0 but it's ada0 in this example since I'm using VirtualBox) that I'll use as a boot key and two regular hard drives (ada1, ada2) that I want to use for a mirror. Go through the installer as you would normally, using only the smaller drive as your / filesystem.

hy4gUJ3.png


Once booted into the minimal base system, we can begin by encrypting the drives we'll be using for the zpool. I'm doing a basic layout, if you want to customize how your drives are encrypted, I'll refer you to the Geli manpage.

Code:
geli init -b -s 4096 ada1
geli init -b -s 4096 ada2
geli attach ada1
geli attach ada2

Next we will set up the zpool with these new encrypted devices. If you require more customization (compression on subdirectories, different checksums, optimized for 4k drives, etc) I'll refer you to this guide.

Code:
zpool create -o altroot=/mnt -o cachefile=/var/tmp/zpool.cache tank mirror /dev/ada1.eli /dev/ada2.eli
zpool export tank
zpool import -o altroot=/mnt -o cachefile=/var/tmp/zpool.cache tank
zpool set bootfs=tank tank
cp /var/tmp/zpool.cache /mnt/zpool.cache

Copy the files from the minimal installation over to the new encrypted pool. You'll want to copy every directory except /boot and /mnt. In my case, that's:

Code:
cd /
cp -Rvp bin dev etc home lib libexec media proc rescue root sbin sys tmp usr var /mnt/
mkdir -p /mnt/mnt/boot

Edit the fstab on the zpool to reflect our /boot being the unencrypted drive, then create a symlink for it.

Code:
vi /mnt/etc/fstab
ln -s /mnt/boot/boot /mnt/boot

In my case, fstab was:

Code:
# Device        Mountpoint      FStype  Options Dump    Pass#
/dev/ada0s1a    /mnt/boot               ufs     rw      1       1

Add these to /boot/loader.conf:

Code:
geom_eli_load="YES"
zfs_load="YES"
vfs.root.mountfrom="zfs:tank"

Add this to /mnt/etc/rc.conf:

Code:
zfs_enable="YES"

Copy over the zpool.cache and reboot:

Code:
cp /mnt/zpool.cache /boot/zfs/zpool.cache
reboot

It should now ask you for a passphrase on startup:

RfHNa4q.png


And once we login...

zhoOl4M.png


That's it! You can remove everything in /mnt/boot except boot.

Sources:
1, 2, 3
 
Back
Top