May 14

Booting Ubuntu on a ZFS Root File System

I recently tried booting Ubuntu 13.04 with a zfs root file system; after the zfs 0.6.1 kernel module was released.  I set this up as a guest on Virtualbox.  Please read the instructions here for Ubuntu:

Above link is very accurate for Ubuntu but I had just a couple small differences for Ubuntu 13.04 64-bit.

System Requirements

  • 64-bit Ubuntu Live CD. (Not the alternate installer, and not the 32-bit installer!)
  • AMD64 or EM64T compatible computer. (ie: x86-64)
  • 8GB disk storage available.
  • 2GB memory minimum.
  • Virtualbox 4.2.12

Step 1: Prepare The Install Environment

1.1 Start the Ubuntu LiveCD and open a terminal at the desktop.

1.2 Switch to a text terminal using Control-F2.  Shutdown X and Unity.  Input these commands at the terminal prompt:

$ sudo -i
# /etc/init.d/lightdm stop
# apt-add-repository --yes ppa:zfs-native/stable
# apt-get update
# apt-get install debootstrap ubuntu-zfs

1.3 Check that the ZFS filesystem is installed and available:

# modprobe zfs
# dmesg | grep ZFS:
ZFS: Loaded module v0.6.1-rc14, ZFS pool version 5000, ZFS filesystem version 5

Step 2: Disk Partitioning

2.1 Use fdisk to create two partitions (100MB boot and 4G root) on the primary storage device.  You can expand the root volume later.  Device was /dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252 in my case.  Your disk names will vary.

The partition table should look like this:

root@ubuntu:~# fdisk -l /dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252
Disk /dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252: 8589 MB, 8589934592 bytes
Device Boot Start End Blocks Id System
/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252-part1 * 63 96389 48163+ be Solaris boot
/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252-part2 96390 7903979 3903795 bf Solaris

Step 3: Disk Formatting

3.1 Format the small boot partition created by Step 2.2 as a filesystem that has stage1 GRUB support like this:

# mke2fs -m 0 -L /boot/grub -j /dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252-part1

3.2 Create the root pool on the larger partition:

# zpool create -o ashift=9 rpool /dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252-part2

3.3 Create a "ROOT" filesystem in the root pool:

# zfs create rpool/ROOT

3.4 Create a descendant filesystem for the Ubuntu system:

# zfs create rpool/ROOT/ubuntu-1

3.5 Dismount all ZFS filesystems.

# zfs umount -a

3.6 Set the mountpoint property on the root filesystem:

# zfs set mountpoint=/ rpool/ROOT/ubuntu-1

3.7 Set the bootfs property on the root pool.

# zpool set bootfs=rpool/ROOT/ubuntu-1 rpool

3.8 Export the pool:

# zpool export rpool

Don't skip this step. The system is put into an inconsistent state if this command fails or if you reboot at this point.

Step 4: System Installation

4.1 Import the pool:

# zpool import -d /dev/disk/by-id -R /mnt rpool

4.2 Mount the small boot filesystem for GRUB that was created in step 3.1:

# mkdir -p /mnt/boot/grub
# mount /dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252-part1 /mnt/boot/grub

4.4 Install the minimal system:

# debootstrap raring /mnt

Step 5: System Configuration

5.1 Copy these files from the LiveCD environment to the new system:

# cp /etc/hostname /mnt/etc/
# cp /etc/hosts /mnt/etc/

5.2 The /mnt/etc/fstab file should be empty except for a comment. Add this line to the /mnt/etc/fstab file:

/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252-part1  /boot/grub  auto  defaults  0  1

5.3 Edit the /mnt/etc/network/interfaces file so that it contains something like this:

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

Customize this file if the new system is not a DHCP client on the LAN.  After you have rebooted and you want network-manager to manage your network connection remove eth0 again.

5.4 Make virtual filesystems in the LiveCD environment visible to the new system and chroot into it:

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

5.5 Install PPA support in the chroot environment like this:

# locale-gen en_US.UTF-8
# apt-get update
# apt-get install ubuntu-minimal software-properties-common

5.6 Install ZFS in the chroot environment for the new system:

# apt-add-repository --yes ppa:zfs-native/stable
# apt-add-repository --yes ppa:zfs-native/grub
# apt-get update
# apt-get install --no-install-recommends linux-image-generic linux-headers-generic
# apt-get install ubuntu-zfs
# apt-get install grub2-common grub-pc
# apt-get install zfs-initramfs
# apt-get dist-upgrade

Choose /dev/sda if prompted to install the MBR loader.

5.7 Set a root password on the new system:

# passwd root

Hint: If you want the ubuntu-desktop package, then install it after the first reboot. If you install it now, then it will start several process that must be manually stopped before dismount.

Step 6: GRUB Installation

Remember: All of Step 6 depends on Step 5.4 and must happen inside the chroot environment.

6.1 Verify that the ZFS root filesystem is recognized by GRUB and that the ZFS modules for GRUB are installed:

# grub-probe /

# ls /boot/grub/i386-pc/zfs*
/boot/grub/i386-pc/zfs.mod  /boot/grub/i386-pc/zfsinfo.mod</code>

6.2 Refresh the initrd files:

# update-initramfs -c -k all

6.3 Update the boot configuration file:

# update-grub

Verify that boot=zfs appears in the boot configuration file:

# grep boot=zfs /boot/grub/grub.cfg
linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.8.0-19-generic root=/dev/sda2 ro boot=zfs $bootfs quiet splash $vt_handoff
linux /ROOT/ubuntu-1/@/ROOT/ubuntu-1@//boot/vmlinuz-3.8.0-19-generic root=ZFS=rpool/ROOT/ubuntu-1/@/ROOT/ubuntu-1 ro boot=zfs $bootfs quiet splash $vt_handoff
linux /ROOT/ubuntu-1/@/ROOT/ubuntu-1@//boot/vmlinuz-3.8.0-19-generic root=ZFS=rpool/ROOT/ubuntu-1/@/ROOT/ubuntu-1 ro single nomodeset boot=zfs $bootfs

Update 1:

If you have issues booting on Ubuntu 13.04 I temporarily fixed two lines manually for the first boot and then once logged in I fixed /boot/grub/grub.cfg as follow for subsequent boots:

#linux /ROOT/ubuntu-1/@/ROOT/ubuntu-1@//boot/vmlinuz-3.8.0-19-generic root=ZFS=rpool/ROOT/ubuntu-1/@/ROOT/ubuntu-1 ro boot=zfs $bootfs quiet splash $vt_handoff
linux /ROOT/ubuntu-1/@/boot/vmlinuz-3.8.0-19-generic root=/dev/sda2 ro boot=zfs $bootfs quiet splash $vt_handoff

#initrd /ROOT/ubuntu-1/@/ROOT/ubuntu-1@//boot/initrd.img-3.8.0-19-generic
initrd /ROOT/ubuntu-1/@/boot/initrd.img-3.8.0-19-generic

Update 2:

Grub issue on Ubuntu 13.04 is being worked:

6.4 Now install the boot loader to the MBR like this:

# grub-install $(readlink -f /dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBb59e0ffb-68fb0252)
Installation finished. No error reported.

Do not reboot the computer until you get exactly that result message. Note that you are installing the loader to the whole disk, not a partition.

Note: The readlink is required because recent GRUB releases do not dereference symlinks.

Step 7: Cleanup and First Reboot

7.1 Exit from the chroot environment back to the LiveCD environment:

# exit

7.2 Run these commands in the LiveCD environment to dismount all filesystems:

# umount /mnt/boot/grub
# umount /mnt/dev
# umount /mnt/proc
# umount /mnt/sys
# zfs umount -a
# zpool export rpool

The zpool export command must succeed without being forced or the new system will fail to start.  If you have problems exporting rpool make sure you really did unmount all the file systems above.