There is a newer version of this guide for Ubuntu 19.10.
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 -n3:1M:+511M -t3:8300 -c3:Boot /dev/disk/by-id/^^ata_disk^^
sgdisk -n2:0:+128M -t2:EF00 -c2:EFI /dev/disk/by-id/^^ata_disk^^
sgdisk -n1:0:0 -t1:8300 -c1:Data /dev/disk/by-id/^^ata_disk^^
sgdisk --print /dev/disk/by-id/^^ata_disk^^
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 512 \
--pbkdf pbkdf2 --hash sha256 /dev/disk/by-id/^^ata_disk^^-part1
cryptsetup luksOpen /dev/disk/by-id/^^ata_disk^^-part1 system
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/system
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:
yes | mkfs.ext4 /dev/disk/by-id/^^ata_disk^^-part3
mount /dev/disk/by-id/^^ata_disk^^-part3 /mnt/system/boot/
mkdir /mnt/system/boot/efi
mkfs.msdos -F 32 -n EFI /dev/disk/by-id/^^ata_disk^^-part2
mount /dev/disk/by-id/^^ata_disk^^-part2 /mnt/system/boot/efi
We need to ensure boot partition auto-mounts:
echo PARTUUID=$(blkid -s PARTUUID -o value /dev/disk/by-id/^^ata_disk^^-part3) \
/boot ext4 noatime,nofail,x-systemd.device-timeout=5s 0 1 >> /mnt/system/etc/fstab
echo PARTUUID=$(blkid -s PARTUUID -o value /dev/disk/by-id/^^ata_disk^^-part2) \
/boot/efi vfat noatime,nofail,x-systemd.device-timeout=5s 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 --make-rslave /dev /mnt/system/dev
mount --rbind --make-rslave /proc /mnt/system/proc
mount --rbind --make-rslave /sys /mnt/system/sys
chroot /mnt/system/ /bin/bash --login
Now we can update our software:
apt update
Immediately 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 keyutils
echo "system UUID=$(blkid -s UUID -o value /dev/disk/by-id/^^ata_disk^^-part1) \
none luks,discard,initramfs,keyscript=decrypt_keyctl" >> /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/efi \
--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 unmount our new environment. If unmount fails, just repeat it until it doesn’t. :)
exit
umount -R /mnt/system
Finally we can correct root’s mount point and reboot:
zfs set mountpoint=/ system/root
reboot
Assuming nothing went wrong, your UEFI system is now ready.
[2019-10-27: Added --make-rslave]
PS: There are versions of this guide using the native ZFS encryption for other Ubuntu versions: 21.10 and 20.04
PPS: For LUKS-based ZFS setup, check the following posts: 20.04, 19.10, and 18.10.