Installing NixOS on a ThinkPad T480s (with encrypted ZFS)
I set up my ThinkPad T480S to run NixOS with native ZFS encryption and a swap partition encrypted with a new random key every boot. Here's how.

I've been running NixOS on my ThinkPad T480s for about 18 months now and when i initally installed it i used the standard installer which used LUKS encryption and ext4 for the filesystem.
All my other Linux systems (apart from the server hosting this blog) use ZFS, so i want to use ZFS on this ThinkPad too. ZFS has its own native encryption so i can ditch LUKS and use that instead.
I'm going to enable Zram support for swap but on the off chance i need more i'm going to create a small swap partition. I don't use hibernation on my laptops so i'll set it up so that the swap partition uses a new random encryption key for every boot.
Partitioning the drive and creating the Zpool
Boot from the NixOS installer and open a terminal. Switch to the root user:
sudo su -
Partition the drive with 1GB EFI, 4GB Swap and rest for ZFS:
parted /dev/nvme0n1 -- mklabel gpt
parted /dev/nvme0n1 -- mkpart ESP fat32 1MB 1GB
parted /dev/nvme0n1 -- mkpart zfs "" 1GB -4GB
parted /dev/nvme0n1 -- mkpart swap linux-swap -4GB 100%
parted /dev/nvme0n1 -- set 1 esp on
Create the encrypted Zpool (change tank
to the desired name):
zpool create -O encryption=on -O keyformat=passphrase \
-O keylocation=prompt -O compression=on -O mountpoint=none \
-O xattr=sa -O acltype=posixacl -o ashift=12 \
tank /dev/nvme0n1p2
Enter the desired encryption passphrase (and again for confirmation).
Create the basic datasets for installation:
zfs create -o mountpoint=legacy tank/root
zfs create -o mountpoint=legacy tank/nix
zfs create -o mountpoint=legacy tank/var
zfs create -o mountpoint=legacy tank/home
Create mountpoints and mount the datasets:
mount -t zfs tank/root /mnt
mkdir /mnt/nix /mnt/var /mnt/home /mnt/boot
mount -t zfs tank/nix /mnt/nix
mount -t zfs tank/var /mnt/var
mount -t zfs tank/home /mnt/home
Format and mount the boot partition:
mkfs.fat -F 32 -n boot /dev/nvme0n1p1
mount -o umask=077 /dev/disk/by-label/boot /mnt/boot
Format and enable the Swap partition:
mkswap -L swap /dev/nvme0n1p3
swapon /dev/nvme0n1p3
Create the hardware-configuration.nix and configuration.nix files:
nixos-generate-config --no-filesystems --root /mnt
Replace the /mnt/etc/nixos/configuration.nix file with the following:
{ config, pkgs, ... }:
{
imports =
[ # Include tweaks from NixOS-Hardware.
<nixos-hardware/lenovo/thinkpad/t480s>
# Include the results of the hardware scan.
./hardware-configuration.nix
];
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.supportedFilesystems = [ "zfs" ];
boot.initrd.systemd.enable = true;
fileSystems."/" = {
device = "tank/root";
fsType = "zfs";
};
fileSystems."/nix" = {
device = "tank/nix";
fsType = "zfs";
};
fileSystems."/var" = {
device = "tank/var";
fsType = "zfs";
};
fileSystems."/home" = {
device = "tank/home";
fsType = "zfs";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/02CA-3441";
fsType = "vfat";
options = [ "fmask=0077" "dmask=0077" ];
};
swapDevices = [
{
device = "/dev/disk/by-partuuid/436dad18-5d2b-49da-a549-b4234f9bd7e0";
randomEncryption.enable = true;
}
];
zramSwap = {
enable = true;
algorithm = "zstd";
};
# Networking
networking = {
hostId = "4b3c47ff";
hostName = "orange";
nftables.enable = true;
firewall.enable = false;
networkmanager.enable = true;
};
# System Settings.
system.stateVersion = "24.11";
time.timeZone = "Europe/London";
console.keyMap = "uk";
i18n.defaultLocale = "en_GB.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "en_GB.UTF-8";
LC_IDENTIFICATION = "en_GB.UTF-8";
LC_MEASUREMENT = "en_GB.UTF-8";
LC_MONETARY = "en_GB.UTF-8";
LC_NAME = "en_GB.UTF-8";
LC_NUMERIC = "en_GB.UTF-8";
LC_PAPER = "en_GB.UTF-8";
LC_TELEPHONE = "en_GB.UTF-8";
LC_TIME = "en_GB.UTF-8";
};
# Services
services = {
libinput.enable = true; # Libinput
fwupd.enable = true; # LVFS Firmware updates
printing.enable = true; # CUPS
flatpak.enable = true; # Flatpak
tailscale.enable = true; # Tailscale
# ZFS
zfs = {
autoScrub.enable = true;
trim.enable = true;
};
# OpenSSH
openssh = {
enable = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
};
};
};
# Enable Wayland, setup Gnome, etc
services.xserver = {
enable = true;
xkb = {
layout = "gb";
variant = "";
};
displayManager.gdm.enable = true;
desktopManager.gnome.enable = true;
excludePackages = [
pkgs.xterm
];
};
# Enable sound with pipewire.
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
# Install some additional packages
environment.systemPackages = with pkgs; [
zip
unzip
wget
lm_sensors
whois
dig
calibre
gnupg
dino
strawberry-qt6
pika-backup
parabolic
tuba
localsend
# Gaming
duckstation
pcsx2
simple64
dolphin-emu
caprice32
# Gnome Packages
gnome-tweaks
gnome-software
gnomeExtensions.tailscale-qs
gnomeExtensions.alphabetical-app-grid
shotwell
celluloid
];
# Exclude some default Gnome packages
environment.gnome.excludePackages = with pkgs; [
geary
gnome-clocks
yelp
gnome-initial-setup
totem
gnome-music
gnome-weather
gnome-tour
gnome-photos
];
# Enable program features
programs = {
firefox = {
enable = true;
languagePacks = [ "en-GB" ];
};
chromium = {
enable = true;
extensions = [
"ponfpcnoihfmfllpaingbgckeeldkhle" # Enhancer for YouTube
"cjpalhdlnbpafiamejdnhcphjbkeiagm" # uBlock Origin
"aapbdbdomjkkjkaonfhkkikfgjllcleb" # Google Translate
];
};
thunderbird.enable = true;
};
# Define a user account. Don't forget to set a password with ‘passwd’.
users.users.USERNAME = {
isNormalUser = true;
description = "FIRSTNAME LASTNAME";
extraGroups = [ "networkmanager" "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3..."
"ssh-ed25519 AAAAC3..."
];
};
}
Edit the above to suit.
The UUID for /boot and the partition UUID for swap will definitely need to changed.
The /boot UUID can be found by running ls -l /dev/disk/by-uuid/
and looking for the UUID pointing to ../../nvme0n1p1
.
The swap partition UUID can be found by running ls -l /dev/disk/by-partuuid/
and looking for the UUID pointing to ../../nvme0n1p3
.
The partition UUID for swap is needed because the standard filesystem UUID will change each boot.
Installation
The configuration.nix file above pulls in hardware tweaks for the T480s from the NixOS-Hardware project. The channel needs to be added for it:
nix-channel --add https://github.com/NixOS/nixos-hardware/archive/master.tar.gz nixos-hardware
nix-channel --update
Then install NixOS
nixos-install
Set the root password after installation.
A password for the user(s) defined in configuration.nix can be set by running:
nixos-enter --root /mnt -c 'passwd USERNAME'
Reboot the system and remove installation media.
Congratulations the ThinkPad T480s is now running NixOS with native ZFS encryption and random-key encrypted swap!