This guide provides an example setup for a single-disk ZFS system with native encryption, accessible for decryption remotely.
This configuration only applies to systemd-boot enabled systems and requires UEFI booting.
This guide is compatible with systems that have secure boot disabled. If you encounter boot issues, check if secure boot needs to be disabled in your UEFI settings.
Replace the highlighted lines with your own disk-id. You can find our your disk-id by executing:
lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT Below is the configuration for disko.nix
{
lib,
...
}:
let
mirrorBoot = idx: {
# suffix is to prevent disk name collisions
name = idx;
type = "disk";
device = "/dev/disk/by-id/${idx}";
content = {
type = "gpt";
partitions = {
"boot" = {
size = "1M";
type = "EF02"; # for grub MBR
priority = 1;
};
"ESP" = lib.mkIf (idx == "nvme-eui.002538b931b59865") {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "nofail" ];
};
};
"root" = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
in
{
imports = [ ];
config = {
boot.loader.systemd-boot.enable = true;
disko.devices = {
disk = {
x = mirrorBoot "nvme-eui.002538b931b59865";
};
zpool = {
zroot = {
type = "zpool";
rootFsOptions = {
compression = "lz4";
acltype = "posixacl";
xattr = "sa";
"com.sun:auto-snapshot" = "true";
mountpoint = "none";
};
datasets = {
"root" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/secret.key";
};
};
"root/nixos" = {
type = "zfs_fs";
options.mountpoint = "/";
mountpoint = "/";
};
"root/home" = {
type = "zfs_fs";
options.mountpoint = "/home";
mountpoint = "/home";
};
"root/tmp" = {
type = "zfs_fs";
mountpoint = "/tmp";
options = {
mountpoint = "/tmp";
sync = "disabled";
};
};
};
};
};
};
};
}
Below is the configuration for disko.nix
{
lib,
...
}:
let
mirrorBoot = idx: {
# suffix is to prevent disk name collisions
name = idx;
type = "disk";
device = "/dev/disk/by-id/${idx}";
content = {
type = "gpt";
partitions = {
"boot" = {
size = "1M";
type = "EF02"; # for grub MBR
priority = 1;
};
"ESP" = lib.mkIf (idx == "nvme-eui.002538b931b59865") {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "nofail" ];
};
};
"root" = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
in
{
imports = [ ];
config = {
boot.loader.systemd-boot.enable = true;
disko.devices = {
disk = {
x = mirrorBoot "nvme-eui.002538b931b59865";
y = mirrorBoot "my-other-disk";
};
zpool = {
zroot = {
type = "zpool";
rootFsOptions = {
compression = "lz4";
acltype = "posixacl";
xattr = "sa";
"com.sun:auto-snapshot" = "true";
mountpoint = "none";
};
datasets = {
"root" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/secret.key";
};
};
"root/nixos" = {
type = "zfs_fs";
options.mountpoint = "/";
mountpoint = "/";
};
"root/home" = {
type = "zfs_fs";
options.mountpoint = "/home";
mountpoint = "/home";
};
"root/tmp" = {
type = "zfs_fs";
mountpoint = "/tmp";
options = {
mountpoint = "/tmp";
sync = "disabled";
};
};
};
};
};
};
};
}
Below is the configuration for initrd.nix.
Replace <yourkey> with your ssh public key.
Replace kernelModules with the ethernet module loaded one on your target machine.
{config, pkgs, ...}:
{
boot.initrd.systemd = {
enable = true;
};
# uncomment this if you want to be asked for the decryption password on login
#users.root.shell = "/bin/systemd-tty-ask-password-agent";
boot.initrd.network = {
enable = true;
ssh = {
enable = true;
port = 7172;
authorizedKeys = [ "<yourkey>" ];
hostKeys = [
"/var/lib/initrd_host_ed25519_key"
"/var/lib/initrd_host_rsa_key"
];
};
};
boot.initrd.availableKernelModules = [
"xhci_pci"
];
# Find out the required network card driver by running `lspci -k` on the target machine
boot.initrd.kernelModules = [ "r8169" ];
} Before starting the installation process, ensure that the SSH public key is copied to the NixOS installer.
ssh-copy-id -o PreferredAuthentications=password -o PubkeyAuthentication=no root@nixos-installer.local ssh root@nixos-installer.local secret.key file in /tmp using nano or another text editor:nano /tmp/secret.key blkdiscard /dev/disk/by-id/<installdisk> clan machines install, only running kexec and disko, with the following command:clan machines install gchq-local --target-host root@nixos-installer --phases kexec,disko ssh root@nixos-installer.local zfs set keylocation=prompt zroot/root CTRL+D authorizedKeys.ssh-keygen -q -N "" -C "" -t ed25519 -f ./initrd_host_ed25519_key
ssh-keygen -q -N "" -C "" -t rsa -b 4096 -f ./initrd_host_rsa_key /mnt directory:scp ./initrd_host* root@nixos-installer.local:/mnt/var/lib/ clan machines install gchq-local --target-host root@nixos-installer --phases install /mnt/boot, change the ZFS mountpoints and unmount all the ZFS volumes by exporting the zpool:umount /mnt/boot
cd /
zfs set -u mountpoint=/ zroot/root/nixos
zfs set -u mountpoint=/tmp zroot/root/tmp
zfs set -u mountpoint=/home zroot/root/home
zpool export zroot initrd_rsa_key and provided port:ssh -p 7172 root@192.168.178.141 systemd-tty-ask-password-agent utility to query a password:systemd-tty-ask-password-agent After completing these steps, your NixOS should be successfully installed and ready for use.
Note: Replace root@nixos-installer.local and 192.168.178.141 with the appropriate user and IP addresses for your setup. Also, adjust <SYS_PATH> to reflect the correct system path for your environment.