1. Download Minimal ISO image and boot from it.

  2. Connect to network. See NixOS manual.

  3. SSH server is enabled by default. To connect, set root password with:

    sudo passwd
  4. Connect from another computer:

    ssh root@
  5. Unique pool suffix. ZFS expects pool names to be unique, therefore it’s recommended to create pools with a unique suffix:

    INST_UUID=$(dd if=/dev/urandom bs=1 count=100 2>/dev/null | tr -dc 'a-z0-9' | cut -c-6)
  6. Identify this installation in ZFS filesystem path:

  7. Root on ZFS configuration file name:

  8. Target disk

    List available disks with:

    ls /dev/disk/by-id/*

    If using virtio as disk bus, use /dev/disk/by-path/*.

    Declare disk array:

    DISK='/dev/disk/by-id/ata-FOO /dev/disk/by-id/nvme-BAR'

    For single disk installation, use:

  9. Choose a primary disk. This disk will be used for primary EFI partition, default to first disk in the array:

    INST_PRIMARY_DISK=$(echo $DISK | cut -f1 -d\ )
  10. Set vdev topology, possible values are:

    • (not set, single disk or striped; no redundancy)

    • mirror

    • raidz1

    • raidz2

    • raidz3


    This will create a single vdev with the topology of your choice. It is also possible to manually create a pool with multiple vdevs, such as:

    zpool create --options \
          poolName \
          mirror sda sdb \
          raidz2 sdc ... \
          raidz3 sde ... \
          spare  sdf ...

    Notice the cost of parity when using RAID-Z. See here and here.

    For boot pool, which must be readable by GRUB, mirrored vdev should always be used for maximum redundancy. This guide will use mirrored bpool for multi-disk setup.

    Refer to zpoolconcepts and zpool-create man pages for details.

  11. Set partition size:

    Set ESP size:


    Set boot pool size. To avoid running out of space while using boot environments, the minimum is 4GB. Adjust the size if you intend to use multiple kernel/distros:


    Set swap size. It’s recommended to setup a swap partition. If you intend to use hibernation, the minimum should be no less than RAM size. Skip if swap is not needed:


    Root pool size, use all remaining disk space if not set: