Installation

Note all commands should be run as root.

Download an installer and burn it to a bootable USB drive. https://www.ventoy.net/en/doc_start.html

Filesystem partitioning

Open a terminal and switch to root to avoid having to prefix everything with sudo.

sudo su

Identify the root partition:

Next, we need to figure out which disk we want to use. I want to wipe and reinstall NixOs on my current linux system. To check which disk your current Linux system is installed on using the /dev/disk/by-id directory, follow these steps:

To find which /dev/disk/by-id entry corresponds to your system disk (/dev/nvme0n1), you can use the following command:

ls -l /dev/disk/by-id/ | grep nvme0n1

In my case this is my first NVMe in this machine so I will be using nvme0n1, but you may see a different number based on what is connected. Let’s start partitioning the disk

For the filesystem, we’re going to create two partitions. We need one, vfat, for the boot and another, zfs, for the rest of the filesystem.

DISK=/dev/nvme0n1

Next, it’s time to partition the actual disk. I’m going to be creating the following partitions:

1 GiB (unencrypted) boot partition The remainder of the drive will be our actual, usable, partition

gdisk "${DISK}"

We can start by creating the first partition of 1GB.

GPT fdisk (gdisk) version 1.0.5

Partition table scan:
  MBR: not present
  BSD: not present
  APM: not present
  GPT: not present

Creating new GPT entries in memory.

Command (? for help): o
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): Y

Command (? for help): n
Partition number (1-128, default 1):
First sector (34-1953525134, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-1953525134, default = 1953525134) or {+-}size{KMGTP}: +1G
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): EF00
Changed type of partition to 'EFI system partition'

Followed by the rest of the filesystem.

Command (? for help): n
Partition number (2-128, default 2): 2
First sector (34-1953525134, default = 2099200) or {+-}size{KMGTP}:
Last sector (2099200-1953525134, default = 1953525134) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help): c
Partition number (1-2): 2
Enter name: root

Write the changes

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to /dev/nvme0n1.
The operation has completed successfully.

Filesystem formatting

Now that we got our partitions creates, let’s go ahead and format them properly.

Starting with the boot partition first.

mkfs.vfat /dev/disk/by-id/VENDOR-ID-part1

Then our zfs partition, but we need to encrypt it first. So, we create the Luks partition. The following command should prompt you to enter your passphrase.

cryptsetup luksFormat /dev/disk/by-id/VENDOR-ID-part2

At this stage, stage we are done with the filesystem formatting and we need to create the zfs pool. To do so, we need to mount the encrypted root filesystem; Luks. Note: The following command will prompt you to enter your passphrase again.

cryptsetup open --type luks /dev/disk/by-id/VENDOR-ID-part2 crypt

This mounts the filesystem in /dev/mapper/crypt. We’ll use that to create the pool.

zpool create -O mountpoint=none rpool /dev/mapper/crypt
zfs create -o mountpoint=legacy rpool/root
zfs create -o mountpoint=legacy rpool/root/nixos
zfs create -o mountpoint=legacy rpool/home

Filesystem mounting

After creating the filesystem, let’s mount everything.

# Mounting filesystem
mount -t zfs rpool/root/nixos /mnt
mkdir /mnt/home
mkdir /mnt/boot
# Mounting home directory
mount -t zfs rpool/home /mnt/home
# Mounting boot partition
mount /dev/disk/by-id/VENDOR-ID-part1 /mnt/boot

Generating NixOs configuration

At this stage, we need a nix configuration to build our system from. I didn’t have any configuration to start from so I generated one.

nixos-generate-config --root /mnt

NixOs configuration

The required configuration bits to be added to /mnt/etc/nixos/configuration.nix are:

boot.supportedFilesystems = [ "zfs" ];
# Make sure you set the networking.hostId option, which ZFS requires:
networking.hostId = "<random 8-digit hex string>";
# See https://nixos.org/nixos/manual/options.html#opt-networking.hostId for more.

# Use the GRUB 2 boot loader.
boot.loader.grub = {
  enable = true;
  version =2;
  device = "nodev";
  efiSupport = true;
  enableCryptodisk = true;
};

boot.initrd.luks.devices = {
 root = {
   device = "/dev/disk/by-uuid/VENDOR-UUID"; ## Use blkid to find this UUID
   # Required even if we're not using LVM
   preLVM = true;
 };
};

To get the networking.hostId use the following command:

head -c 8 /etc/machine-id

To get the luks encrypted partition use the following command:

blkid | grep $DISK

The vendor UUID you should look for should be the one with PARTLABEL="root"

Note: You might have to comment out the boot.loader.grub section out in order to run nixos-install

NixOS installation

If we’re done with all of the configuration as described above, we should be able to build a bootable system. Let’s try that out by installing NixOS.

nixos-install

Resources

https://nixos.wiki/wiki/ZFS

https://blog.lazkani.io/posts/nixos-on-encrypted-zfs/

https://ipetkov.dev/blog/installing-nixos-and-zfs-on-my-desktop/