ZFS on laptop with encrypted /home

With Ubuntu 19.10 it’s simple to get a workstation with boot and root on ZFS. But what’s missing from the install is encryption. This is how I did it.

I suggest you first have:

  • basic zfs knowledge
  • good linux knowledge
  • no important data on the target system
  • more than 4 GB RAM
  • SSD or better

How-to

  • Install Ubuntu as normal, but choose “use ZFS”. It’s marked as experimental, but that’s because how Ubuntu uses it may change in later releases. The code it self is solid.
  • After install is done, you’re left with a bpool and an rpool. I will only focus on encrypting /home/<user>. I’ll use username john in this example.
  • Your layout will look something like this:
$ zfs list -r rpool
NAME                                               USED  AVAIL     REFER  MOUNTPOINT
rpool                                              165G   293G       96K  /
rpool/ROOT                                        18,8G   293G       96K  none
rpool/ROOT/ubuntu_oyzpo3                          18,8G   293G     3,92G  /
rpool/ROOT/ubuntu_oyzpo3/usr                      1,06M   293G       96K  /usr
rpool/ROOT/ubuntu_oyzpo3/usr/local                 992K   293G      144K  /usr/local
rpool/ROOT/ubuntu_oyzpo3/var                      13,4G   293G       96K  /var
rpool/ROOT/ubuntu_oyzpo3/var/games                 320K   293G       96K  /var/games
rpool/ROOT/ubuntu_oyzpo3/var/lib                  4,36G   293G     3,72G  /var/lib
rpool/ROOT/ubuntu_oyzpo3/var/lib/AccountServices   320K   293G       96K  /var/lib/AccountServices
rpool/ROOT/ubuntu_oyzpo3/var/lib/NetworkManager   3,67M   293G      208K  /var/lib/NetworkManager
rpool/ROOT/ubuntu_oyzpo3/var/lib/apt              87,0M   293G     74,9M  /var/lib/apt
rpool/ROOT/ubuntu_oyzpo3/var/lib/dpkg             87,4M   293G     41,2M  /var/lib/dpkg
rpool/ROOT/ubuntu_oyzpo3/var/log                   574M   293G      170M  /var/log
rpool/ROOT/ubuntu_oyzpo3/var/mail                 2,25M   293G      104K  /var/mail
rpool/ROOT/ubuntu_oyzpo3/var/snap                 8,46G   293G     8,46G  /var/snap
rpool/ROOT/ubuntu_oyzpo3/var/spool                10,4M   293G     3,51M  /var/spool
rpool/ROOT/ubuntu_oyzpo3/var/www                   320K   293G       96K  /var/www
rpool/USERDATA                                     141G   293G       96K  /
rpool/USERDATA/john_75qybu                         140G   293G      126G  /home/john
rpool/USERDATA/root_75qybu                        1,07G   293G     1,07G  /root

We want to replace rpool/USERDATA/john_75qybu with a new, encrypted file system.

  • Create another temporary user, smith, and log out of john and in as smith.
  • Set filesystem name in a variable, so you can copy/paste the rest: $oldfs=”rpool/USERDATA/john_75qybu”; $newfs=”rpool/USERDATA/john_crypt”
  • Unmount: sudo zfs umount $oldfs
  • Reset mountpoint: sudo zfs set mountpoint=none $oldfs
  • Create a new, encrypted file system for your main user: sudo zfs create -o encryption=on -o keyformat=passphrase $newfs
  • Set mountpoint: sudo zfs set mountpoint=/home/john $newfs
  • Mount: sudo zfs mount -a
  • If you get complaints on missing key, run: sudo zfs load-key -a and then mount again.

If you had any data on the unencrypted home dir, you can mount it anywhere else (zfs set mountpoint=/mnt ...), and copy data.

Last thing you need to do is enable key loading at boot.

  • Create the file /etc/systemd/system/zfskey-tank@.service as:
[Unit]
Description=Load %I encryption keys
Before=systemd-user-sessions.service
Before=zfs-mount.service
After=zfs-import.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/bash -c 'systemd-ask-password "Encrypted ZFS password for %I" --no-tty  | zfs load-key -a'

[Install]
WantedBy=zfs-mount.service

Note that I’ve changed the suggested example from Arch Wiki which ended in zfs load-key %I to zfs load-key -a. That way all encrypted filesystems will be mounted.

  • And enable: $ sudo systemctl enable zfskey-tank@john_crypt

Reboot and check that everything works. If you have trouble logging in, you can log in as smith and check what fails. Unlocking, mounting or access rights. It will look the same in a zfs list, but you should see a difference if you run:

$ sudo zfs get encryption rpool/USERDATA/john_crypt
NAME                         PROPERTY    VALUE        SOURCE
rpool/USERDATA/john_crypt  encryption  aes-256-ccm  -

If everything works, you can move along to setting up snapshots or other fancy zfs stuff. =)

Resources: