This guide will walk you through installing NixOS with:
/ and /homeBoot from the NixOS installation media (USB drive or DVD) and open a terminal.
We'll use sgdisk to partition the disk. Replace /dev/sda with your actual disk (find it with lsblk):
# Create EFI boot partition (512MB)
sgdisk -n 1:1M:+512M -t 1:EF00 /dev/sda
# Create main partition for LUKS container (rest of disk)
sgdisk -n 2:0:0 -t 2:8300 /dev/sda
# Format the second partition as LUKS container
cryptsetup --type luks2 luksFormat /dev/sda2
# Open the LUKS container
cryptsetup luksOpen /dev/sda2 encrypted_root
# Create ZFS partition (everything except space for swap)
# First, let's check the size of the LUKS container
blockdev --getsize64 /dev/mapper/encrypted_root
# Create swap partition (8GB) and ZFS partition (remaining space)
# Using sgdisk on the mapped device
echo -e "start=\$(sgdisk -E /dev/mapper/encrypted_root)\nsgdisk -n 1:0:+8G /dev/mapper/encrypted_root\nsgdisk -n 2:0:\${start} /dev/mapper/encrypted_root" | bash
# Format swap
mkswap -L swap /dev/mapper/encrypted_root1
swapon /dev/mapper/encrypted_root1
# Create ZFS pool on the second inner partition
zpool create -f -O encryption=on -O keyformat=passphrase -O keylocation=prompt \
-O compression=lz4 -O atime=off -O normalization=formD -O xattr=sa -O acltype=posixacl \
-m none -R /mnt rpool /dev/mapper/encrypted_root2
# Create ZFS datasets for root and home
zfs create -o mountpoint=legacy rpool/ROOT
zfs create -o mountpoint=legacy rpool/ROOT/root
zfs create -o mountpoint=legacy rpool/ROOT/nix
zfs create -o mountpoint=legacy rpool/home
# Create a blank snapshot for potential rollbacks
zfs snapshot rpool/ROOT/root@blank
# Mount the ZFS datasets
mount -t zfs rpool/ROOT/root /mnt
mkdir -p /mnt/nix /mnt/home
mount -t zfs rpool/ROOT/nix /mnt/nix
mount -t zfs rpool/home /mnt/home
# Mount the boot partition
mkdir -p /mnt/boot
mount /dev/sda1 /mnt/boot
nixos-generate-config --root /mnt
Edit /mnt/etc/nixos/configuration.nix to include the following settings:
{ config, pkgs, ... }:
{
imports = [
# Include the results of the hardware scan
./hardware-configuration.nix
];
# Bootloader configuration
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Enable ZFS support
boot.supportedFilesystems = [ "zfs" ];
# ZFS auto-snapshot service
services.zfs.autoSnapshot.enable = true;
# ZFS auto-trim service
services.zfs.trim.enable = true;
# Filesystem mappings
fileSystems."/" = {
device = "rpool/ROOT/root";
fsType = "zfs";
};
fileSystems."/nix" = {
device = "rpool/ROOT/nix";
fsType = "zfs";
};
fileSystems."/home" = {
device = "rpool/home";
fsType = "zfs";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/$(blkid -s UUID -o value /dev/sda1)";
fsType = "vfat";
};
# LUKS encryption settings
boot.initrd.luks.devices."encrypted_root".device = "/dev/disk/by-uuid/$(blkid -s UUID -o value /dev/sda2)";
# Enable zram swap (instead of disk swap)
zramSwap = {
enable = true;
memoryPercent = 100; # Use up to 100% of RAM (will be limited to ~8GB by default)
priority = 100;
algorithm = "zstd"; # Efficient compression algorithm
};
# Additional settings (customize as needed)
networking.hostName = "nixos"; # Define your hostname here
networking.networkmanager.enable = true;
# Select internationalisation properties
i18n.defaultLocale = "en_US.UTF-8";
console.keyMap = "us";
# Enable the OpenSSH daemon
services.openssh.enable = true;
# Define a user account
users.users.yourusername = {
isNormalUser = true;
description = "Your Name";
extraGroups = [ "networkmanager" "wheel" ];
packages = with pkgs; [
# Add packages for the user
];
};
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It's perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "24.05"; # Change this when first installing NixOS
}
nixos-install
passwd
reboot
As an alternative, you can use this automated script that performs most of the above steps:
#!/usr/bin/env bash
# NixOS install with ZFS on LUKS encryption and zram swap
#
# sda
# ├─sda1 BOOT
# └─sda2 LINUX (LUKS CONTAINER)
# ├─encrypted_root1 SWAP
# └─encrypted_root2 ZFS
set -e
pprint () {
local cyan="\e[96m"
local default="\e[39m"
# ISO8601 timestamp + ms
local timestamp
timestamp=$(date +%FT%T.%3NZ)
echo -e "${cyan}${timestamp} $1${default}" 1>&2
}
# Set DISK - adjust this to your disk
DISK="/dev/sda"
read -p "> Do you want to wipe all data on $DISK ?" -n 1 -r
echo # move to a new line
if [[ "$REPLY" =~ ^[Yy]$ ]]
then
# Clear disk
wipefs -af "$DISK"
sgdisk -Zo "$DISK"
fi
pprint "Creating boot (EFI) partition"
sgdisk -n 1:1M:+512M -t 1:EF00 "$DISK"
BOOT="$DISK""1"
pprint "Creating Linux partition"
sgdisk -n 2:0:0 -t 2:8300 "$DISK"
LINUX="$DISK""2"
# Inform kernel
partprobe "$DISK"
sleep 1
pprint "Format BOOT partition $BOOT"
mkfs.vfat "$BOOT"
pprint "Creating LUKS container on $LINUX"
cryptsetup --type luks2 luksFormat "$LINUX"
LUKS_DEVICE_NAME=encrypted_root
cryptsetup luksOpen "$LINUX" "$LUKS_DEVICE_NAME"
LUKS_DISK="/dev/mapper/$LUKS_DEVICE_NAME"
# SWAP partition (8GB)
sgdisk -n 1:0:+8G -t 1:8200 $LUKS_DISK
SWAP="${LUKS_DISK}1"
# ZFS partition (remaining space)
sgdisk -n 2:0:0 -t 2:8300 $LUKS_DISK
ZFS="${LUKS_DISK}2"
# Inform kernel
partprobe "$LUKS_DISK"
sleep 1
pprint "Enable SWAP on $SWAP"
mkswap $SWAP
swapon $SWAP
pprint "Create ZFS pool on $ZFS"
zpool create -f -O encryption=on -O keyformat=passphrase -O keylocation=prompt \
-O compression=lz4 -O atime=off -O normalization=formD -O xattr=sa -O acltype=posixacl \
-m none -R /mnt rpool "$ZFS"
pprint "Create ZFS datasets"
zfs create -o mountpoint=legacy rpool/ROOT
zfs create -o mountpoint=legacy rpool/ROOT/root
zfs create -o mountpoint=legacy rpool/ROOT/nix
zfs create -o mountpoint=legacy rpool/home
zfs snapshot rpool/ROOT/root@blank
pprint "Mount ZFS datasets"
mount -t zfs rpool/ROOT/root /mnt
mkdir -p /mnt/nix
mount -t zfs rpool/ROOT/nix /mnt/nix
mkdir -p /mnt/home
mount -t zfs rpool/home /mnt/home
mkdir -p /mnt/boot
mount "$BOOT" /mnt/boot
pprint "Generate NixOS configuration"
nixos-generate-config --root /mnt
# Add LUKS configuration to hardware-configuration.nix
LINUX_DISK_UUID=$(blkid --match-tag UUID --output value "$LINUX")
HARDWARE_CONFIG=$(mktemp)
cat < "$HARDWARE_CONFIG"
boot.initrd.luks.devices."$LUKS_DEVICE_NAME".device = "/dev/disk/by-uuid/$LINUX_DISK_UUID";
boot.zfs.devNodes = "/dev/disk/by-partuuid/";
CONFIG
pprint "Append configuration to hardware-configuration.nix"
sed -i "\$e cat $HARDWARE_CONFIG" /mnt/etc/nixos/hardware-configuration.nix
pprint "Installation prepared. Now edit /mnt/etc/nixos/configuration.nix to add zram swap and other settings, then run nixos-install"
If you encounter issues unlocking the LUKS container during boot, you may need to enter the passphrase at boot time. The system will prompt you for the encryption passphrase before mounting the root filesystem.
If the ZFS pool doesn't import correctly at boot, you can manually import it:
zpool import -f rpool
After installation, you can verify zram is working:
cat /proc/swaps
zcat /sys/block/zram*/mm_stat
zpool statuscryptsetup luksHeaderBackup /dev/sda2 --header-backup-file luks-header-backup.imgFor more information about NixOS installation, refer to the official NixOS manual.