HOWTO install Ubuntu 16.04 to a Native ZFS Root Filesystem

HOWTO install Ubuntu 16.04 to a Native ZFS Root Filesystem

System Requirements

  • 64-bit Ubuntu 16.04 boot/install CD/USB/DVD, full installer not server, netboot or alternative
  • 8GB free disk/partition available
  • 4GB memory recommended

Ubuntu 16.04 (xenial) has ZFS utilities natively, in “universe” repository.

Install ZFS packages and activate kernel module.

If you’re installing fresh off of 16.04 media, it does not comes with zfs tools. You have to add “universe” to the repository list in /etc/apt/sources.list, then install the zfs tools.

$ sudo echo "deb xenial universe" | sudo tee -a /etc/apt/sources.list
$ sudo apt-get update
$ sudo apt-get install zfsutils-linux zfs-initramfs
$ sudo modprobe zfs

Create disk labels and partitions

This section is for disks you want to erase completely and make into ZFS pool members.

grub-probe doesn’t support whole-disk device pools [TODO: Check these facts], so the disks we use in zfs pools must hold a disk label, and the partitions in it are pool devices instead. [Actually, grub-probe doesn’t support luks either. grub-probe might not support a lot of things, but that can be worked around by manually setting GRUB_DEVICE in /etc/default/grub to the real or mapped device which holds the zfs pool(s). This may also require editing line 139 of/usr/sbin/grub_mkconfig to ignore grub-probe errors. ]

AND, a single large partition can be mis-interpreted as whole-disk [TODO: Check these facts], so add a little partition at the end to keep the device scanner from finding it. We might as well use that as an EFI system partition. [TODO: Does ZFS handle EFI system data already, without this? EDIT: Almost certainly not. It might even be a good idea to also create a boot ext2 partition, similar to how booting from luks usually works. ]

As an example, to initialize a disk (using disk id because it’s safer to use descriptions than arbitrary floating letters like sd-a, b, c):

$ sudo parted -- /dev/disk/by-id/ata-ST9999999999_10000000 \
mklabel gpt Y \
mkpart zfs zfs 0% -512MB \
mkpart efi fat32 -512MB 100% \
set 2 boot on

Create the pool

Hereafter we’ll assume a pool name of “alexandria”, after the famous library, in the examples, but you can use anything you wish. It’s a proper name, and you get to decide what to call this group of storage devices.

Also, this uses the “raidz” organizing type for its new virtual device. Read the “zpool” man page for what the different virtual device types are. This is up to you. Don’t just follow this example. Know what organization you want to have with your devices and fill in the pieces here. You can also add devices later.

$ sudo zpool create -o ashift=12 \
-o autoexpand=on \
-O compression=lz4 \
alexandria \
raidz /dev/disk/by-id/ata-ST9999999999_10000000-part1 /dev/disk/by-id/ata-ST9999999999_02000000-part1

$ sudo zpool export alexandria     # important step!

$ sudo zpool import -d /dev/disk/by-id alexandria

$ sudo zpool status -v alexandria
  pool: alexandria
 state: ONLINE
  scan: none requested

    NAME                                 STATE     READ WRITE CKSUM
    alexandria                           ONLINE       0     0     0
      raidz2-0                           ONLINE       0     0     0
        ata-ST9999999999_10000000-part1  ONLINE       0     0     0
        ata-ST9999999999_02000000-part1  ONLINE       0     0     0

errors: No known data errors

Create the root filesystem

Assuming pool name “alexandria”…

$ sudo zfs create alexandria/ROOT
$ sudo zfs create alexandria/ROOT/ubuntu-1

Copy data from old root to new

If you’re installing fresh, you can skip this section. [TODO: *Since Ubiquity doesn’t support ZFS yet, you actually cannot do a straight fresh install. You have to install to a temporary place and copy the files to zfs. This can be a second device, or a Zvol on the pool. Install Ubuntu using Ubiquity, mount the zvol/device, then continuing with below.]

Assuming pool name “alexandria”…

$ sudo mkdir /tmp/oldroot
$ sudo mount --bind / !$
$ sudo rsync -avPX /tmp/oldroot/. /alexandria/ROOT/ubuntu-1/. # [Do we need `-H`, `-A`, or `-W` flags? Why use `-P`? Also, it might be simpler to use `--one-file-system` rsync flag, like so: `rsync --one-file-system -aAXHW / /alexandria/ROOT/ubuntu-1/`. But are we really instructing people to do the copy on a running system?]

Clean up fstab and prepare grub

Assuming pool name “alexandria”…

Remove the root mount lines from /alexandria/ROOT/ubuntu-1/etc/fstab

[TODO: We don’t need to set boot, rpool, or bootfs. root=ZFS=alexandria/ROOT/ubuntu-1is all that’s necessary. Moreover, update-grub via /etc/grub/10_linux does plenty of work to detect the correct zpool and volume and set root itself. In /etc/default/grub, I only had to specify GRUB_DEVICE because grub-probe failed (see note above).]

In /alexandria/ROOT/ubuntu-1/etc/default/grub, add “boot” “rpool” and “bootfs” variables to GRUB_CMDLINE_LINUX .

GRUB_CMDLINE_LINUX="boot=zfs rpool=alexandria bootfs=alexandria/ROOT/ubuntu-1"

Then, install grub.

[ The boot and EFI partitions must be mounted to /alexandria/ROOT/ubuntu-1/boot and/alexandria/ROOT/ubuntu-1/boot/efi. ]

$ for d in proc sys dev; do sudo mount --bind /$d /alexandria/ROOT/ubuntu-1/$d; done
$ sudo chroot /alexandria/ROOT/ubuntu-1/
# update-grub

Finish installation

Migrating path users, skip this section.

If you’re in the install-fresh path, you will need to signal the advanced settings where you will be mounting the zfs device. Don’t format it. ZFS carries its own formatting and you should leave it alone. [TODO: verify ubiquity will recognize zfs devices as mountable and ready for install]

Then, continue the install.


Reference link-:


Post a comment