December 6, 2016

Setup encrypted Ubuntu with ZFS on LUKS

This post is just combining the information from Ubuntu 16.04 Root on ZFS and Encrypted ZFS Ubuntu Installation.

First, start up your target machine using an Ubuntu Live ISO. When you’ll see the desktop, just press Ctrl + Alt + F1 and login with ubuntu and blank password. Let’s prepare the system for SSH, as things are much easier there. You can also skip this and do things locally, of course.

Prepare SSH

passwd
sudo su
systemctl stop lightdm # save some precious memory ;)
apt update
apt install openssh-server -y

Now we can connect to the target machine via SSH.

Setup

Install neccessary packages:

apt install zfsutils-linux cryptsetup debootstrap dosfstools gdisk -y

I’m going to take the only disk and create one big partition for ZFS plus some system partitions (/boot, EFI). Please consider this as an example, you probably want your layout to be different.

DISK="/dev/$(lsblk --nodeps --include 253 --raw --noheadings | cut -d ' ' -f1)"
echo $DISK
sgdisk -o $DISK
sgdisk -n1:1M:+256M -t1:8300 $DISK # for /boot
sgdisk -n2:0:+256M -t2:EF00 $DISK # EFI
sgdisk -n9:-8M:0 -t9:BF07 $DISK # reserved
sgdisk -n3:0:0 -t3:8300 $DISK  # everything else

Now let’s setup the crypto part:

cryptsetup luksFormat -c aes-xts-plain64 -s 512 -h sha512 ${DISK}3
cryptsetup luksOpen ${DISK}3 rpool_crypt

And now the ZFS thingy (full copy from ZoL project plus some additional steps for LUKS):

zpool create -o ashift=12 -O atime=off -O canmount=off -O compression=lz4 -O normalization=formD -O mountpoint=/ -R /mnt rpool /dev/mapper/rpool_crypt
zfs create -o canmount=off -o mountpoint=none rpool/ROOT
zfs create -o canmount=noauto -o mountpoint=/ rpool/ROOT/ubuntu
zfs mount rpool/ROOT/ubuntu
zfs create -o setuid=off rpool/home
zfs create -o mountpoint=/root rpool/home/root
zfs create -o canmount=off -o setuid=off -o exec=off rpool/var
zfs create -o com.sun:auto-snapshot=false rpool/var/cache
zfs create rpool/var/log
zfs create rpool/var/spool
zfs create -o com.sun:auto-snapshot=false -o exec=on rpool/var/tmp
chmod 1777 /mnt/var/tmp
debootstrap xenial /mnt
zfs set devices=off rpool

Prepare the boot and EFI partitions:

mkfs.ext4 -F -m 0 -L /boot -j ${DISK}1
mkdosfs -F 32 -n EFI ${DISK}2
echo "/dev/mapper/rpool_crypt / zfs defaults 0 0"  >> /mnt/etc/fstab
echo "PARTUUID=$(blkid -s PARTUUID -o value ${DISK}1) /boot auto defaults 0 0" >> /mnt/etc/fstab
echo "PARTUUID=$(blkid -s PARTUUID -o value ${DISK}2) /boot/efi vfat defaults 0 1" >> /mnt/etc/fstab

Prepare the chroot:

TARGET_HOSTNAME="test"
echo "$TARGET_HOSTNAME" > /mnt/etc/hostname
sed -i 's,localhost,localhost\n127.0.1.1\t'$TARGET_HOSTNAME',' /mnt/etc/hosts
mount --rbind /dev  /mnt/dev
mount --rbind /proc /mnt/proc
mount --rbind /sys  /mnt/sys
chroot /mnt /bin/bash --login

Setup the system:

ln -s /proc/self/mounts /etc/mtab
ln -s /dev/mapper/rpool_crypt /dev/rpool_crypt # Without this symbolic link update-grub will complain that is can't find the canonical path and error. 
echo 'ENV{DM_NAME}=="rpool_crypt", SYMLINK+="rpool_crypt"' > /etc/udev/rules.d/99-rpool_crypt.rules # Assure that future kernel updates will succeed by always creating the symbolic link.
locale-gen en_US.UTF-8
dpkg-reconfigure tzdata
mount /boot
mkdir /boot/efi
mount /boot/efi
cat > /etc/apt/sources.list << EOF
deb http://archive.ubuntu.com/ubuntu xenial main universe
deb-src http://archive.ubuntu.com/ubuntu xenial main universe

deb http://security.ubuntu.com/ubuntu xenial-security main universe
deb-src http://security.ubuntu.com/ubuntu xenial-security main universe

deb http://archive.ubuntu.com/ubuntu xenial-updates main universe
deb-src http://archive.ubuntu.com/ubuntu xenial-updates main universe
EOF
apt update
apt install --yes ubuntu-minimal
apt install --yes --no-install-recommends linux-image-generic
apt install --yes zfs-initramfs cryptsetup grub-efi
addgroup --system lpadmin
addgroup --system sambashare
passwd
echo "rpool_crypt UUID=$(blkid -s UUID -o value ${DISK}3) none luks,discard" >> /etc/crypttab
update-initramfs -c -k all
sed -i 's,GRUB_CMDLINE_LINUX="",GRUB_CMDLINE_LINUX="boot=zfs",' /etc/default/grub
update-grub
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu --recheck --no-floppy
apt-get clean
zfs snapshot rpool/ROOT/ubuntu@install
exit

Almost there:

mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | xargs -i{} umount -lf {}
zpool export rpool
reboot

Continue to setup your system