A complete guide to install Arch Linux on ZFS, "The last word in filesystems", step by step.
In summary, ZFS is a stable, fast and advanced filesystem with many features such as snapshotting, native encryption and caching in memory. In this post we'll go through the complete process of installing Arch Linux on ZFS, starting with creating a bootable USB drive with ZFS support.
Building an Arch ISO with ZFS support
The default ISO image you can download from the Arch Linux website does not support ZFS.
That's why we have to create our own using the
archiso tool. We will install the tool from
the Arch Linux repositories.
docker run --rm --privileged -it -v "$(pwd)/out":/root/iso/out archlinux
- Install the
archisotool, create a work directory and copy the releng profile to it.
sudo pacman -Sy archiso mkdir ~/iso cp -r /usr/share/archiso/configs/releng/* ~/iso
- Add the ArchZFS repository to the Pacman configuration for our build and tell
archisoto install the ZFS DKMS module and ZFS utils to our resulting ISO.
echo -e ' [archzfs] Server = https://archzfs.com/$repo/$arch SigLevel = Optional TrustAll' >> ~/iso/pacman.conf echo -e ' linux-headers archzfs-dkms zfs-utils' >> ~/iso/packages.x86_64
- Next, build the ISO. This can take some time…
sudo mkarchiso -vo ~/iso/out ~/iso
- Finally, write the ISO to a USB drive using your favorite tool, restart your computer and boot it.
Before getting started, I set my keymap and make the console font larger.
loadkeys de-latin1 setfont ter-132n
Once everything is set up, start
parted on the drive you want to install
Arch Linux to (
/dev/nvme0n1 in my case) and create a new GPT partition table and partitions.
Though it's not covered in this post, it should be no problem to install Arch Linux on ZFS
alongside existing operating systems. If you want to do this, skip creating a new partition table
and partition the disk to your liking.
parted -a opt /dev/nvme0n1 print # Display current partition table mklabel gpt # Create new partition table, will destroy data! mkpart primary 5MB% 512MB # Boot/EFI mkpart primary 512MB 100% # remaining space set 1 boot on # Boot flag set 1 esp on # EFI flag quit
Creating the ZFS Pool
Let's create a new ZFS pool named "zroot". The options are a solid
default for a pool for day to day desktop use. We'll build our final root filesystem in
/mnt in the installer OS will be
/ in the installed system.
Make sure to match the capitalization of the
zpool create \ -o ashift=12 \ -O acltype=posixacl -O canmount=off \ -O dnodesize=auto -O normalization=formD \ -O atime=off -O xattr=sa -O mountpoint=none \ -R /mnt zroot /dev/nvme0n1p2 # ← Partition 2
You need at least one dataset for your root filesystem
/. I'm creating an
additional dataset for my
/home directory, so I can take snapshots of my base
system and it separately. You can create additional datasets if you want.
# Root dataset zfs create -o canmount=noauto -o mountpoint=/ zroot/rootfs # Set the root dataset as bootfs zpool set bootfs=zroot/rootfs zroot # Additional datasets… zfs create zroot/rootfs/home
Next, mount the root dataset. This will also mount any child datasets you created.
zfs mount zroot/rootfs
Finally, we need to tell ZFS to create a
zpool.cache file. This file contains information
about out ZFS pool and can be loaded at boot time instead of re-importing the pool each time.
/etc/zfs is part of the installer, we have to copy the cache file to our soon-to-be
mkdir -p /mnt/etc/zfs zpool set cachefile=/etc/zfs/zpool.cache zroot cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache
Setting up the boot partition
Format the boot partition with FAT32 and mount it into
mkfs.vfat /dev/nvme0n1p1 mkdir /mnt/boot mount /dev/nvme0n1p1 /mnt/boot
Generate filesystem table
Now that all filesystems for the new Arch installation are mounted in
we can generate the final
fstab using the
genfstab -U -p /mnt >> /mnt/etc/fstab
Install base packages
pacstrap to install the base packages and a desktop environment. You can pick another
desktop environment or shell and leave out SSH or ZSH if you want to.
pacstrap /mnt base base-devel linux linux-headers linux-firmware grub efibootmgr \ nano zsh gdm gnome openssh
After chrooting into your new system, the first thing to do is to add the ArchZFS repository and install the ZFS DKMS module. After that, you can install additional packages you want in your new system.
arch-chroot /mnt echo -e ' [archzfs] Server = https://archzfs.com/$repo/x86_64' >> /etc/pacman.conf # ArchZFS GPG keys (see https://wiki.archlinux.org/index.php/Unofficial_user_repositories#archzfs) pacman-key -r DDF7DB817396A49B2A2723F7403BD972F75D9D76 pacman-key --lsign-key DDF7DB817396A49B2A2723F7403BD972F75D9D76 pacman -Sy zfs-dkms # Optional packages pacman -S nvidia-dkms intel-ucode
/etc/mkinitcpio.conf, find the line that defines build hooks (
HOOKS=(...)) and add the ZFS hooks
HOOKS=(base udev autodetect modconf block keyboard keymap zfs filesystems)
After that, generate the image with
mkinitcpio -p linux
Finally, let's set up GRUB. First, make sure to create the
Edit the file
/etc/default/grub and add
zfs=zroot/rootfs to the kernel parameters
GRUB_CMDLINE_LINUX_DEFAULT. Generate the GRUB configuration files and install
GRUB with the according tools:
mkdir /boot/grub nano /etc/default/grub # GRUB_CMDLINE_LINUX_DEFAULT="zfs=zroot/rootfs" grub-mkconfig -o /boot/grub/grub.cfg grub-install --target=x86_64-efi --efi-directory=/boot
Finalizing the installation
We need to enable some services for systemd to be able to handle and mount our ZFS datasets.
Remember to enable your display manager service, too (
gdm in my case).
systemctl enable zfs.target zfs-import-cache \ zfs-mount zfs-import.target gdm
The following are some common tasks like setting the correct timezone, locale, hostname,
creating a new user and enable the use of
# Set time and timezone ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime # Change according to location… hwclock --systohc # Sync with HW clock # Configure locales echo -e ' de_DE.UTF-8 UTF-8 en_US.UTF-8 UTF-8' >> /etc/locale.gen echo 'KEYMAP=de-latin1' > /etc/vconsole.conf echo 'LANG=de_DE.UTF-8' > /etc/locale.conf locale-gen # Set hostname echo myhostname > /etc/hostname echo -e '127.0.0.1 localhost\n::1 localhost\n127.0.1.1 myhostname' >> /etc/hosts groupadd sudo useradd -m -G sudo <username> EDITOR=nano visudo # uncomment sudo group passwd <username>
You're done! Exit the chroot with
exit, unmount all filesystems, export the ZFS pool and reboot
into your new OS!
exit # Back in the installer shell… umount -R /mnt zfs umount -a zpool export -a
- Mar 23, 2021: Import and verify against ArchZFS keys in final installation
- Jul 26, 2021: Set the
bootfsseparately after creating the pool and root dataset, as it doesn't seem to work (anymore?) during zpool creation.
- Jul 27, 2021: Remove NetworkManager as required service (you can still install and enable it if you want to use it)