ZFS Install Guide

Introduction

This wiki will show you how to install Funtoo on ZFS (rootfs).

Prerequisites

Important

ZFS designed for 64-bit systems. We only recommending and supporting 64-bit platforms and installations!

ZFS recommendation is to control entire disk, hence, guide reflecting only installing ZFS on whole disk and legacy boot. Installing on UEFI requires separate partition for /boot, formatted into FAT32 and not covered here, though, installation on UEFI is certainly possible. Guide also not describing anything related to encryption.

Downloading the ISO (With ZFS)

In order to install Funtoo on ZFS, you will need an environment such as live media with ZFS tools provided. The following guide will utilize the Ubuntu Desktop 16.04 (live) DVD for amd64.

  • Download from [1]

Creating a bootable USB from ISO (From a Linux Environment)

After you download the iso, you can do the following steps to create a bootable USB:

Note

The size of the iso is approximately 1.5GB.

Insert your blank USB media into a USB port. Shortly after this, inspect the kernel ring buffer with dmesg to identify the device name of your USB storage.

[  +5.533491] usb 6-2: new SuperSpeed USB device number 4 using xhci_hcd
[  +0.022995] usb 6-2: New USB device found, idVendor=1b1c, idProduct=1a0c
[  +0.000006] usb 6-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0.000003] usb 6-2: Product: Voyager Mini 3.0
[  +0.000003] usb 6-2: Manufacturer: Corsair
[  +0.000002] usb 6-2: SerialNumber: 0123456789ABCDEF
[  +0.001095] usb-storage 6-2:1.0: USB Mass Storage device detected
[  +0.000080] scsi host15: usb-storage 6-2:1.0
[  +1.000772] scsi 15:0:0:0: Direct-Access     Corsair  Voyager Mini 3.0 PMAP PQ: 0 ANSI: 6
[  +0.000615] sd 15:0:0:0: Attached scsi generic sg6 type 0
[  +0.000110] sd 15:0:0:0: [sdg] 60566016 512-byte logical blocks: (31.0 GB/28.9 GiB)
[  +0.000209] sd 15:0:0:0: [sdg] Write Protect is off
[  +0.000004] sd 15:0:0:0: [sdg] Mode Sense: 2b 00 00 08
[  +0.000227] sd 15:0:0:0: [sdg] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[  +0.359532] sd 15:0:0:0: [sdg] Attached SCSI removable disk

In this example we see [sdg] meaning that the device is /dev/sdg.

A quick and easy way to create a bootable USB is to write the ISO data to the USB device using dd.

# dd if=/path/to/iso/ubuntu-16.04-desktop-amd64.iso of=/dev/sdg bs=4K
Once this has completed remove and use this USB to boot the target system that will receive Funtoo Linux.

Booting the ISO

Using legacy (BIOS) boot mode, boot the iso and allow ubuntu to load the graphical environment. You will be presented with a "Welcome" dialog (title Install (as superuser)). Select the option "Try Ubuntu".

Once the desktop has loaded open the search bar by left-clicking on the top-left icon ("Search your computer"). Pressing Alt+F1 should also open this search bar. Search for and open the Terminal application.

In the terminal, issue the following commands to install and load the required ZFS module.

ubuntu@ubuntu:~$ sudo -i
root@ubuntu:~# apt-add-repository universe
root@ubuntu:~# apt update
root@ubuntu:~# apt install --yes debootstrap gdisk zfs-initramfs
verify that the ZFS kernel module has loaded

root@ubuntu:~#  dmesg | grep ZFS
[  377.595348] ZFS: Loaded module v0.6.5.6-0ubuntu10, ZFS pool version 5000, ZFS filesystem version 5

Drive Partitions

We are letting ZFS automatically partition the drive. This ideal for our example using a single disk and legacy (BIOS) boot.

Creating of pool

Create a ZFS Storage Pool using a single whole disk

root@ubuntu:~# zpool create -f -o ashift=12 -o cachefile=/tmp/zpool.cache -O normalization=formD -O atime=off -m none -R /mnt/funtoo rpool /dev/disk/by-id/foo

The options used here are

optiondescription
createUse zpool to create a ZFS Storage Pool.
-fForce the use of the selected disk.
-o ashift=12Alignment of the pool to underlying hard drive sectors. The recommended value is 12, which corresponds to 2^12 Bytes or 4 KiB. This value is typical for HDD's nowadays. Can only be set once at pool creation.
-o cachefile=/tmp/zpool.cacheCreate a pool configuration cache and place it in /tmp. This will be required for our Funtoo install.
-O normalization=formDRecommended. Set the default Unicode (UTF-8) normalization for future filesystems (created within this pool) to 'formD'.
-O atime=offOptional. As a default preference, set future filesystems (created within this pool) to not update file access time. Useful if wanting to reduce writes to disk (e.g. Solid State Drives). Can cause problems for mailers and other software relying on file access-time data.
-m noneDo not set mountpoint for this storage pool. (This guide will address this later).
-R /mnt/funtooAlternate root directory. Essentially a temporary 'mount point' for our pool.
rpoolThe name of this ZFS Storage Pool. The pool name is irrelevant, however rpool will be used throughout this guide.
/dev/disk/by-id/fooThe path to the physical disk. e.g. /dev/disk/by-id/ata-Samsung_SSD_840_EVO_120GB_123456789ABCDEF. Known in 'ZFS-speak' as a 'VDEV'.

Please note that the options 'ashift' and 'cachefile' are preceded with a lowercase '-o', while 'normalization' and 'atime' are preceded with an uppercase '-O'.

Without additional options this will create our storage pool and enable all 'features' available under version 0.6.5.6. The pool will be automatically mounted at the (temporary) location /mnt/funtoo.

To confirm the presence of our newly created pool

root@ubuntu:~# zpool status
  pool: rpool
 state: ONLINE
  scan: none requested
config:

	NAME                                             STATE     READ WRITE CKSUM
	rpool                                            ONLINE       0     0     0
	  ata-Samsung_SSD_840_EVO_120GB_123456789ABCDEF  ONLINE       0     0     0

errors: No known data errors

Create ZFS Datasets

Now we will create one or more ZFS datasets within our storage pool. These will contain Funtoo Linux.

Create the Root file system (Required)

#  zfs create -o mountpoint=none -o canmount=off rpool/ROOT
#  zfs create -o mountpoint=/ rpool/ROOT/funtoo

Create optional Datasets

Described below optional datasets are examples. It's up to users to perform creation of their own datasets.

Home
#  zfs create -o mountpoint=/home rpool/HOME
Build directory
#  zfs create -o mountpoint=/var/tmp/portage -o compression=lz4 -o sync=disabled rpool/FUNTOO/build
Swap on ZFS

With some careful tuning a swap partition can be created on a ZFS 'volume' [2]. For a 2GB swapfs:

#  zfs create -V 2G -b $(getconf PAGESIZE) -o logbias=throughput -o sync=always -o primarycache=metadata rpool/swap
#  mkswap /dev/zvol/rpool/swap
#  swapon /dev/zvol/rpool/swap

Notice that swap on ZFS is known of having stability issues. If decided to use swap, please, take following into account: Always use long /dev/zvol aliases in configuration files. Never use a short /dev/zdX device name.

To confirm the presence of the filesystems that we have created

root@ubuntu:~# zfs list -t all
NAME                USED  AVAIL  REFER  MOUNTPOINT
rpool               660K  19.3G    96K  none
rpool/HOME           96K  19.3G    96K  /mnt/funtoo/home
rpool/ROOT          192K  19.3G    96K  none
rpool/ROOT/funtoo    96K  19.3G    96K  /mnt/funtoo

Make the root filesystem bootable

Important

Do not skip this!

When booting from ZFS, you must specify a boot device and a root file system within the pool that was identified by the boot device. By default, the dataset selected for booting is the one identified by the pool's bootfs property.

# zpool set bootfs=rpool/ROOT/funtoo rpool

Installing Funtoo

Now that initial ZFS pool created, datasets ready, we can perform stage3 unpack and basic system installation. This part does not differ much from regular Funtoo Linux installation. http://www.funtoo.org/Install#Installing_the_Stage_3_tarball. We recommend using funtoo-current stages for ZFS.

#  cd /mnt/funtoo
#  wget http://build.funtoo.org/funtoo-current/x86-64bit/generic_64/stage3-latest.tar.xz
Extract the contents with the following command, substituting in the actual name of your stage 3 tarball (in case of arch optimized stage).

#  tar xpf stage3-latest.tar.xz
Now we need to create chroot environment by following:

# cd /mnt/funtoo
# mount -t proc none proc
# mount --rbind /sys sys
# mount --rbind /dev dev
Important step is to copy ZFS cache we created at the very beginning of our rpool creation into chroot.

# mkdir -p /mnt/funtoo/etc/zfs
# cp /tmp/zpool.cache /mnt/funtoo/etc/zfs/zpool.cache
You'll also want to copy over resolv.conf in order to have proper resolution of Internet hostnames from inside the chroot:

# cp /etc/resolv.conf /mnt/funtoo/etc/

We are ready to chroot

# chroot /mnt/funtoo /bin/bash
# export PS1="(chroot) $PS1"; cd

Configuring your system

Configure your system according to the main Install Guide. During startup ZFS Filesystems will be mounted without the need of entries in /etc/fstab. Important step would be commenting of all entries except other partitions such as CD-ROMs, tmpfs, etc. should still be included in /etc/fstab, if used.

If you created a swap volume earlier, add an appropriate entry to /etc/fstab.

#  echo /dev/zvol/rpool/swap none swap defaults 0 0 >> /etc/fstab

Notice that swap on ZFS is known of having stability issues. If decided to use swap, please, take following into account: Always use long /dev/zvol aliases in configuration files. Never use a short /dev/zdX device name.

Next, update the portage tree:

# emerge --sync
# env-update
# source /etc/profile

Installing ZFS userspace and bootloader

Installing the ZFS userspace tools and kernel modules

When using stable Funtoo, it's needed to add keywords for zfs ebuilds as they are only have unstable keywords. Using your favorite editor, create and edit file as below: /etc/portage/package.accept_keywords so that it contains

/etc/portage/package.accept_keywords - example using ZFS 0.6.5.7
=sys-fs/zfs-0.6.5.7 **
=sys-fs/zfs-kmod-0.6.5.7 **
=sys-kernel/spl-0.6.5.7 **
Install the ZFS packages, syncing the portage tree first if required:

# emerge --sync
# emerge --ask sys-fs/zfs
Once successfully merged, add the following services to the boot runlevel of OpenRC:

# rc-update add zfs-import boot
# rc-update add zfs-mount boot

Add another two services, this time to the default runlevel:

# rc-update add zfs-share default
# rc-update add zfs-zed default

Create a ZFS-friendly initramfs

The Funtoo stage3 includes a linux kernel and initramfs. The initramfs is designed to mount and start Funtoo Linux on a variety of file systems. The initramfs contained within the stage3 will NOT mount and start Funtoo in our ZFS storage pool. We must create an updated 'ZFS-friendly' initramfs.

Optional: Update to the latest sys-kernel/genkernel (package not on wiki - please add):

# emerge --oneshot sys-kernel/genkernel
Use genkernel to create an initramfs capable of mounting our ZFS Storage Pool via the --zfs switch. Adjust --makeopts according to your available threads:

# genkernel initramfs --no-clean --no-mountboot --makeopts=-j4 --kernel-config=/usr/src/linux/.config --zfs
* Funtoo Linux Genkernel; Version 3.4.40.11-funtoo
* Running with options: initramfs --no-clean --no-mountboot --makeopts=-j4 --kernel-config=/usr/src/linux/.config --zfs

* Linux Kernel 4.5.2-1 for x86_64...
* .. with config file /usr/src/linux-debian-sources-4.5.2/.config
* busybox: >> Using cache
* initramfs: >> Initializing...
*         >> Appending base_layout cpio data...
*         >> Appending auxilary cpio data...
*         >> Copying keymaps
*         >> Appending busybox cpio data...
*         >> Appending modules cpio data...
*         >> Appending zfs cpio data...
cp: cannot stat ‘/etc/zfs/zdev.conf’: No such file or directory
* Could not copy file /etc/zfs/zdev.conf for ZFS
*         >> Appending blkid cpio data...
*         >> Appending modprobed cpio data...
*         >> Compressing cpio data (.xz)...

* WARNING... WARNING... WARNING...
* Additional kernel cmdline arguments that *may* be required to boot properly...
* add "dozfs" for ZFS volume management support
* add either "real_root=ZFS" (bootfs autodetection) or "real_root=ZFS=<dataset>" to boot from a ZFS dataset

* Do NOT report kernel bugs as genkernel bugs unless your bug
* is about the default genkernel configuration...
* 
* Make sure you have the latest ~arch genkernel before reporting bugs.
Confirming the presence of the new initramfs:

# ls /boot/*genkernel*
/boot/initramfs-genkernel-x86_64-4.5.2-1

Installing GRUB 2

GRUB 2 must be built with support for ZFS Storage Pools on a single disk. This is achieved using the 'libzfs' USE flag.

# echo "sys-boot/grub libzfs" >> /etc/portage/package.use
Note

If you have defined GRUB_PLATFORMS in your /etc/portage/make.conf, please ensure that it includes 'pc': e.g. GRUB_PLATFORMS="efi-64 pc".

This is required for booting in BIOS (non-UEFI) mode as described in this guide.

Now install GRUB

# emerge grub

Configuring the Bootloader

When zpool created our storage pool (rpool), it created partitions under a GPT scheme. In order to boot Funtoo Linux on a GPT partion under legacy (BIOS) boot, sys-boot/grub requires a small partition, called BIOS boot partition. By design, ZFS (zpool) left a very small unpartitioned space at the beginning of the disk. We will use sgdisk, which is part of sys-apps/gptfdisk to format this free space into a BIOS boot partition.

# sgdisk -a1 -n2:48:2047 -t2:EF02 -c2:"BIOS boot partition" /dev/disk/by-id/ata-Samsung_SSD_840_EVO_120GB_123456789ABCDEF
To avoid problems with GRUB, use partx to refresh the list of partitions that are 'seen' by the kernel, using the appropriate /dev/sda, /dev/sdb, ... that corresponds to your drive.

# partx -u /dev/sda
A quick check to verify that GRUB 2 sees/supports ZFS:

# touch /etc/mtab
# grub-probe /
zfs
Installing GRUB2 to disk is as easy as:

# grub-install /dev/disk/by-id/ata-Samsung_SSD_840_EVO_120GB_123456789ABCDEF
Installing for i386-pc platform.
Installation finished. No error reported.
Now it's time for us to create grub's configuration file. First we must edit a few GRUB 2 settings in /etc/default/grub:

Important

The following is required to boot Funtoo Linux on ZFS!

Replace the line

/etc/default/grub - before
#GRUB_CMDLINE_LINUX=""

with

/etc/default/grub - after
GRUB_CMDLINE_LINUX="dozfs real_root=ZFS=rpool/ROOT/funtoo"

Now create GRUB 2 configuration file:

# grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/kernel-debian-sources-x86_64-4.5.2-1
Found initrd image: /boot/initramfs-genkernel-x86_64-4.5.2-1
done
A quick check to verify that the GRUB ZFS module is in place:

# ls /boot/grub/*/zfs.mod
/boot/grub/i386-pc/zfs.mod

Final configuration

Configure your the Network according to of the Installation Guide.

Set the root password.

(chroot) # passwd
Exit the chroot and export your ZFS Storage Pool.

(chroot) # exit
# umount -lR {dev,proc,sys}
# cd /
# zpool export rpool
Restart to boot into Funtoo Linux on ZFS Root!

After reboot

Snapshot

Take a snapshot of your Funtoo at installation.

# zfs snapshot rpool/ROOT/funtoo@install

The use of snapshots, including the sending of snapshots as a backup method, are not covered in this guide. See Further Reading.

ZFS Adjustable Replacement Cache (ARC) size

The Adjustable Replacement Cache (ARC) is a fundamental part of ZFS. Aaron Toponce has written an article explaining the operation of the ARC - link.

Without configuration, ZFS will use up to 50% of your memory (RAM) for the ARC. It is possible to change this maximum. There are different ways to achieve this on both a temporary and persistent basis. One such way is to create and edit the file /etc/modprobe.d/zfs.conf which affects the ZFS kernel module.

/etc/modprobe.d/zfs.conf - set maximum ARC size to 4 GiB
options zfs zfs_arc_max=4294967296

where zfs_arc_max is set to a value in Bytes. After configuring this file, re-generate the initramfs. Rebooting will then apply this change.

To apply this change immediately without a reboot, issue the command:

#  echo 4294967296 >> /sys/module/zfs/parameters/zfs_arc_max
Reference: https://wiki.gentoo.org/wiki/ZFS#ARC

After Kernel or ZFS updates

The default Funtoo Linux kernel - Package:Debian-sources, Package:Debian-sources/pt-br - does not automatically build a ZFS-capable initramfs. Similarly, the package sys-fs/zfs and its dependencies do not automatically build a ZFS-capable initramfs.

The recreation of an initramfs after each kernel update is likely to be required for Funtoo Linux on ZFS root to continue to boot. Similarly, sys-fs/zfs updates should also be followed by a regeneration of initramfs. This is particularly true for updates to sys-fs/zfs that introduce new storage pool features.

Follow the earlier instructions to create a new initramfs.

# genkernel initramfs --no-clean --no-mountboot --makeopts=-j4 --kernel-config=/usr/src/linux/.config --zfs

Further Reading

ZFS has many interesting features not covered by this guide.

Useful information and instructions can be found in the online reference manuals. See man zpool and man zfs.

Aaron Toponce's Zpool/ZFS Administration Guides - https://pthree.org/2012/12/04/zfs-administration-part-i-vdevs

ZFS on Linux - http://www.zfsonlinux.org

ZFS - Gentoo Wiki - https://wiki.gentoo.org/wiki/ZFS

Troubleshooting

Forgot to reset password?

You will need to chroot into Funtoo on ZFS root if you forgot to set the root password. Repeat the earlier instructions to load the the live CD/USB, including the installing of ZFS kernel modules.

When the ZFS kernel modules are loaded, your existing ZFS Storage Pool - rpool - will be imported automatically. This will also result in an attempt to mount the various ZFS filesystems that you created. The mounting of your root partition (/) will fail since this location is not empty - / is allocated to the live CD/USB distribution!

# zpool status
  pool: rpool
 state: ONLINE
  scan: none requested
config:

	NAME                                             STATE     READ WRITE CKSUM
	rpool                                            ONLINE       0     0     0
	  ata-Samsung_SSD_840_EVO_120GB_123456789ABCDEF  ONLINE       0     0     0

errors: No known data errors
To get around this issue, firstly, manually export the pool.

# zpool export rpool
# zpool list
no pools available
Now import your storage pool using the following command.

# zpool import -o cachefile=/tmp/zpool.cache -R /mnt/funtoo -d /dev/disk/by-id/ rpool

This will import rpool and place your Funtoo install at /mnt/funtoo. Follow the earlier set of instructions to chroot into your Funtoo Installation on ZFS root.

Will not mount on first reboot?

Follow the above instructions to import and mount your storage pool (rpool) and chroot back into your Funtoo environment.

Things to check:

  • Was the bootfs property of rpool set? Use zpool get bootfs rpool to check
  • Was /tmp/zpool.cache copied into /mnt/funtoo/etc/zfs/ prior to chroot and creating the initramfs?
  • Was genkernel initramfs run with the --zfs switch and --kernel-config pointing to the correct configuration file?
  • Was GRUB installed and configured correctly?

Unable to add universe repository in Ubuntu?

See http://askubuntu.com/questions/761592/unable-to-apt-get-dist-upgrade-on-a-persistent-ubuntu-16-04-usb