Jump to content

User:2r/NixOS on ZFS: Difference between revisions

From NixOS Wiki
imported>2r
No edit summary
imported>2r
No edit summary
Line 87: Line 87:
Boot pool can be encrypted with LUKS1 to prevent initrd tempering, however ZFS on LUKS is discouraged on root pool as LUKS abstracts physical devices and thus not desirable. Also, data needs to be encrypted per disk, thus slower than per file, as with ZFS native encryption.
Boot pool can be encrypted with LUKS1 to prevent initrd tempering, however ZFS on LUKS is discouraged on root pool as LUKS abstracts physical devices and thus not desirable. Also, data needs to be encrypted per disk, thus slower than per file, as with ZFS native encryption.


ZFS native encryption does not encrypt dataset paths and default properties. Custom properties containing colon <code>custom:property</code> is encrypted. Also, as ZFS currently does not support replacing master key, once the passphrase/keyfile is compromised, the encrypted dataset must be destroyed to protect confidentiality. Therefore, users are advised to choose a strong password at the beginning.
ZFS native encryption does not encrypt dataset paths and default properties. Custom properties containing colon <code>custom:property</code> is encrypted.
 
Also, as ZFS currently does not support replacing master key, once the passphrase/keyfile is compromised, the encrypted dataset must be destroyed to protect confidentiality. Therefore, users are advised to choose a strong password at the beginning.
 
=== Preparations ===
Download NixOS 64 Bit Minimal ISO image and SHA-256 checksum. Verify checksum and write the image to an external disk. Boot the computer from the disk afterwards.
 
After booting the computer, optionally configure SSH server and connect from another computer via SSH.
 
=== Identify target disks ===
List available disks with
<pre>ls -d /dev/disk/by-id/* | grep -v part</pre>
 
=== Partition ===
<pre>for i in {/dev/disk/by-id/disk1,/dev/disk/by-id/disk2}; do
sgdisk --zap-all $i
sgdisk -n1:1M:+1G -t1:EF00 $i
sgdisk -n2:0:+4G -t2:BE00 $i
sgdisk -n3:0:0 -t3:BF00 $i
 
# with swap
# sgdisk -n3:0:-8G -t3:BF00 $i
# sgdisk -n4:0:0  -t4:8308 $i
 
# with BIOS
# sgdisk -a1 -n5:24K:+1000K -t5:EF02 $i
done</pre>
 
=== Create pools ===
==== Multi-disk ====
Change
<pre>zpool create \
... \
/dev/disk/by-id/disk1-partX</pre>
to
<pre>zpool create \
... \
mirror \ # or raidz1 (discouraged), raidz2, raidz3
/dev/disk/by-id/disk1-partX \
/dev/disk/by-id/disk2-partX</pre>
==== Boot pool ====
<pre>zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -d -o feature@async_destroy=enabled \
    -o feature@bookmarks=enabled \
    -o feature@embedded_data=enabled \
    -o feature@empty_bpobj=enabled \
    -o feature@enabled_txg=enabled \
    -o feature@extensible_dataset=enabled \
    -o feature@filesystem_limits=enabled \
    -o feature@hole_birth=enabled \
    -o feature@large_blocks=enabled \
    -o feature@lz4_compress=enabled \
    -o feature@spacemap_histogram=enabled \
    -O acltype=posixacl \
    -O canmount=off \
    -O compression=lz4 \
    -O devices=off \
    -O normalization=formD \
    -O relatime=on \
    -O xattr=sa \
    -O mountpoint=none \
    -R /mnt \
    bpool \
    /dev/disk/by-id/disk1-part2</pre>
==== Root pool ====
<pre>zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -R /mnt \
    -O acltype=posixacl \
    -O canmount=off \
    -O compression=zstd \
    -O dnodesize=auto \
    -O normalization=formD \
    -O relatime=on \
    -O xattr=sa \
    -O mountpoint=none \
    rpool \
    /dev/disk/by-id/disk1-part3</pre>
=== Create datasets ===
==== Boot container ====
<pre>zfs create \
-o canmount=off \
-o mountpoint=none \
bpool/sys</pre>
==== Root container ====
Encrypted
<pre>zfs create \
-o canmount=off \
-o mountpoint=none \
-o encryption=on \
-o keylocation=prompt \
-o keyformat=passphrase \
rpool/sys</pre>
Unencrypted
<pre>zfs create \
-o canmount=off \
-o mountpoint=none \
rpool/sys</pre>
==== System datasets ====

Revision as of 02:33, 6 March 2021

This is a userspace draft and is not supported by NixOS Wiki.

Enable ZFS on Existing Installation

Add the following lines to configuration:

boot.supportedFilesystems = [ "zfs" ];
networking.hostId = "deadbeef";

Host ID should be unique, generate one with head -c 8 /etc/machine-id.

Rebuild system with nixos-rebuild switch.

Install NixOS on ZFS

Layout

Partitions

As swap on ZFS will cause deadlock and does not support hibernation, a separate swap partition should be created.

GPT partition table
ESP bpool rpool swap BIOS boot sector
Filesystem vfat ZFS, feature limited for GRUB compatibility. ZFS swap N/A
Content grubx64.efi /boot / swap N/A
Encryption No, can be validated with Secure Boot LUKS1 ZFS Encrytion random/LUKS2 N/A

Datasets

As NixOS lacks a service to handle native ZFS mounting at boot, such as zfs-mount-generator, all mountable datasets must be created with mountpoint=legacy to be mounted with fileSystems option.

Datasets with canmount=off mountpoint=none are used as containers, that is, no data is stored directly under such datasets, but child datasets can inherit their properties or imitate directory structures, such as /var/log.

Dataset layout
Containers mountpoint canmount comment
bpool sys BOOT default /boot noauto
rpool sys ROOT default / noauto
DATA local / off container for datasets that do not need backup, such as /nix
safe / off container for datasets that need backup, such as /{root,home,home,user}

Encryption

Boot pool can be encrypted with LUKS1 to prevent initrd tempering, however ZFS on LUKS is discouraged on root pool as LUKS abstracts physical devices and thus not desirable. Also, data needs to be encrypted per disk, thus slower than per file, as with ZFS native encryption.

ZFS native encryption does not encrypt dataset paths and default properties. Custom properties containing colon custom:property is encrypted.

Also, as ZFS currently does not support replacing master key, once the passphrase/keyfile is compromised, the encrypted dataset must be destroyed to protect confidentiality. Therefore, users are advised to choose a strong password at the beginning.

Preparations

Download NixOS 64 Bit Minimal ISO image and SHA-256 checksum. Verify checksum and write the image to an external disk. Boot the computer from the disk afterwards.

After booting the computer, optionally configure SSH server and connect from another computer via SSH.

Identify target disks

List available disks with

ls -d /dev/disk/by-id/* | grep -v part

Partition

for i in {/dev/disk/by-id/disk1,/dev/disk/by-id/disk2}; do
sgdisk --zap-all $i
sgdisk -n1:1M:+1G -t1:EF00 $i
sgdisk -n2:0:+4G -t2:BE00 $i
sgdisk -n3:0:0 -t3:BF00 $i

# with swap
# sgdisk -n3:0:-8G -t3:BF00 $i
# sgdisk -n4:0:0   -t4:8308 $i

# with BIOS
# sgdisk -a1 -n5:24K:+1000K -t5:EF02 $i
done

Create pools

Multi-disk

Change

zpool create \
... \
/dev/disk/by-id/disk1-partX

to

zpool create \
... \
mirror \ # or raidz1 (discouraged), raidz2, raidz3
/dev/disk/by-id/disk1-partX \
/dev/disk/by-id/disk2-partX

Boot pool

zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -d -o feature@async_destroy=enabled \
    -o feature@bookmarks=enabled \
    -o feature@embedded_data=enabled \
    -o feature@empty_bpobj=enabled \
    -o feature@enabled_txg=enabled \
    -o feature@extensible_dataset=enabled \
    -o feature@filesystem_limits=enabled \
    -o feature@hole_birth=enabled \
    -o feature@large_blocks=enabled \
    -o feature@lz4_compress=enabled \
    -o feature@spacemap_histogram=enabled \
    -O acltype=posixacl \
    -O canmount=off \
    -O compression=lz4 \
    -O devices=off \
    -O normalization=formD \
    -O relatime=on \
    -O xattr=sa \
    -O mountpoint=none \
    -R /mnt \
    bpool \
    /dev/disk/by-id/disk1-part2

Root pool

zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -R /mnt \
    -O acltype=posixacl \
    -O canmount=off \
    -O compression=zstd \
    -O dnodesize=auto \
    -O normalization=formD \
    -O relatime=on \
    -O xattr=sa \
    -O mountpoint=none \
    rpool \
    /dev/disk/by-id/disk1-part3

Create datasets

Boot container

zfs create \
 -o canmount=off \
 -o mountpoint=none \
 bpool/sys

Root container

Encrypted

zfs create \
 -o canmount=off \
 -o mountpoint=none \
 -o encryption=on \
 -o keylocation=prompt \
 -o keyformat=passphrase \
 rpool/sys

Unencrypted

zfs create \
 -o canmount=off \
 -o mountpoint=none \
 rpool/sys

System datasets