Installing UEFI ZFS Root on Ubuntu 19.04

As rumors of Ubuntu 19.04 including ZFS installer proved to be a bit premature, I guess it’s time for a slight adjustment to my previous ZFS instructions.

Again, all this is just a derivation on ZFS-on-Linux project’s instruction for older version.

As before, we first need to get into root prompt:

$ sudo -i

Followed by getting a few basic packages ready:

# apt-add-repository universe
# apt update
# apt install --yes debootstrap gdisk zfs-initramfs

Disk setup is quite simple with only two partitions:

# sgdisk --zap-all             /dev/disk/by-id/ata_disk

# sgdisk -n2:1M:+511M -t2:EF00 /dev/disk/by-id/ata_disk
# sgdisk -n1:0:0      -t1:8300 /dev/disk/by-id/ata_disk

# sgdisk --print               /dev/disk/by-id/ata_disk
Number  Start (sector)    End (sector)  Size       Code  Name
   1         1050624        67108830   31.5 GiB    8300
   2            2048         1050623   512.0 MiB   8300

I believe full disk encryption should be a no-brainer so of course we set up LUKS:

# cryptsetup luksFormat -q --cipher aes-xts-plain64 --key-size 256 \
      --pbkdf pbkdf2 --hash sha256 /dev/disk/by-id/ata_disk-part1
# cryptsetup luksOpen /dev/disk/by-id/ata_disk-part1 luksSystem

Creating ZFS stays the same as before:

# zpool create -o ashift=12 -O atime=off -O canmount=off -O compression=lz4 -O normalization=formD \
      -O xattr=sa -O mountpoint=none system /dev/mapper/luksSystem
# zfs create -o canmount=noauto -o mountpoint=/mnt/system/ system/root
# zfs mount system/root

Getting basic installation on our disks follows next:

# debootstrap disco /mnt/system/
# zfs set devices=off system
# zfs list

And then we setup EFI boot partition:

# mkdosfs -F 32 -n EFI /dev/disk/by-id/ata_disk-part2
# mount /dev/disk/by-id/ata_disk-part2 /mnt/system/boot/

We need to ensure boot partition auto-mounts:

# echo PARTUUID=$(blkid -s PARTUUID -o value /dev/disk/by-id/ata_disk-part2) /boot vfat noatime,nofail,x-systemd.device-timeout=1 0 1 >> /mnt/system/etc/fstab
# cat /mnt/system/etc/fstab

Before we start using anything, we should prepare a few necessary files:

# echo "hostname" > /mnt/system/etc/hostname
# sed 's/ubuntu/hostname/' /etc/hosts > /mnt/system/etc/hosts
# sed '/cdrom/d' /etc/apt/sources.list > /mnt/system/etc/apt/sources.list
# cp /etc/netplan/*.yaml /mnt/system/etc/netplan/

If you are installing via WiFi, you might as well copy your credentials:

# mkdir -p /mnt/system/etc/NetworkManager/system-connections/
# cp /etc/NetworkManager/system-connections/* /mnt/system/etc/NetworkManager/system-connections/

With chroot we can get the first taste of our new system:

# mount --rbind /dev  /mnt/system/dev
# mount --rbind /proc /mnt/system/proc
# mount --rbind /sys  /mnt/system/sys
# chroot /mnt/system/ /bin/bash --login

Now we can update our software:

# apt update

Imediatelly followed with locale and time zone setup:

# locale-gen --purge "en_US.UTF-8"
# update-locale LANG=en_US.UTF-8 LANGUAGE=en_US
# dpkg-reconfigure --frontend noninteractive locales

# dpkg-reconfigure tzdata

Now we install Linux image and basic ZFS boot packages:

# apt install --yes --no-install-recommends linux-image-generic
# apt install --yes zfs-initramfs

Since we’re dealing with encrypted data, our cryptsetup should be also auto mounted:

# apt install --yes cryptsetup

# echo "luksSystem UUID=$(blkid -s UUID -o value /dev/disk/by-id/ata_disk-part1) none luks,discard,initramfs" >> /etc/crypttab
# cat /etc/crypttab

Now we get grub started:

# apt install --yes grub-efi-amd64

And update our boot environment again (seeing errors is nothing unusual):

# update-initramfs -u -k all

And then we finalize our grup setup:

# update-grub
# grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Ubuntu \
      --recheck --no-floppy

Finally we get the rest of desktop system:

# apt-get install --yes ubuntu-desktop samba linux-headers-generic
# apt dist-upgrade --yes

We can omit creation of the swap dataset but I always find it handy:

# zfs create -V 4G -b $(getconf PAGESIZE) -o compression=off -o logbias=throughput -o sync=always \
      -o primarycache=metadata -o secondarycache=none system/swap
# mkswap -f /dev/zvol/system/swap
# echo "/dev/zvol/system/swap none swap defaults 0 0" >> /etc/fstab
# echo RESUME=none > /etc/initramfs-tools/conf.d/resume

If one is so inclined, /home directory can get a separate dataset too:

# rmdir /home
# zfs create -o mountpoint=/home system/home

Only remaining thing before restart is to create user:

# adduser user
# usermod -a -G adm,cdrom,dip,lpadmin,plugdev,sambashare,sudo user
# chown -R user:user /home/user

As install is ready, we can exit our chroot environment and reboot:

# exit
# reboot

You will get stuck after the password prompt as our mount point for system dataset is wrong. That’s easy to correct:

# zfs set mountpoint=/ system/root
# exit
# reboot

Assuming nothing went wrong, your UEFI system is now ready.

6 thoughts to “Installing UEFI ZFS Root on Ubuntu 19.04”

  1. What about doing a:
    # zpool export system
    # zpool import -N system
    # zfs set mountpoint=/ system/root
    before the reboot?

  2. After mounting dev, proc and sys they should be made rslaves:

    mount –make-rslave /mnt/system/proc
    mount –make-rslave /mnt/system/dev
    mount –make-rslave /mnt/system/sys

    This makes unmounting them less of a fresh hell. Also I’m not sure if there’s a reason for this, but you have the partition numbers backwards. Shouldn’t the ESP partition be 1 and the ZFS partition be 2?

    1. ESP partition has to be physically at the beginning of disk. However, it can be any number between 1 to 128. It’s matter of personal preference which number you give it. I like to give number 1 to my biggest partition and work from there. However, all this would work with EFI as the first partition too, i.e.:

      sgdisk -n1:1M:+511M -t1:EF00 /dev/disk/by-id/ata_disk
      sgdisk -n2:0:0      -t2:8300 /dev/disk/by-id/ata_disk
      

      As long as -part1 and -part2 suffixes are swapped too, there is no difference.

  3. This was awesome, thanks! I did this before with 16.04 and 18.04, and probably could have used the 18.04 directions for 19.04, but it was nie to have 19.04 specific directions.

    Worked like a charm!

    -Mark

Leave a Reply to Lars Cancel reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.