Go to file
Thomas Avé a2ad25a8a4
Many fixes
2026-08-22 21:22:45 +07:00
home Many fixes 2026-08-22 21:22:45 +07:00
hosts Many fixes 2026-08-22 21:22:45 +07:00
.gitignore Update gitignore 2024-04-07 20:38:36 +02:00
README.md Many fixes 2026-08-22 21:22:45 +07:00
flake.lock Update flake.lock 2026-08-11 10:19:51 +02:00
flake.nix Many fixes 2026-08-22 21:22:45 +07:00

README.md

Dotfiles

NixOS

Install instructions for NixOS. First open a shell with vim and git:

nix-shell -p git vim

EXT4

parted /dev/nvme0n1 -- mklabel gpt
parted /dev/nvme0n1 -- mkpart ESP fat32 1MB 512MB
parted /dev/nvme0n1 -- mkpart root ext4 512MB 100%
parted /dev/nvme0n1 -- set 1 esp on

mkfs.fat -F 32 -n BOOT /dev/nvme0n1p1
mkfs.ext4 -L NixOS /dev/nvme0n1p2

mount /dev/disk/by-label/NixOS /mnt
mkdir -p /mnt/boot
mount -o umask=077 /dev/disk/by-label/BOOT /mnt/boot
nixos-generate-config --root /mnt

ZFS

First stop the zfs-zed service, and unload the ZFS kernel modules:

systemctl stop zfs-zed
lsmod | grep zfs | cut -d' ' -f1 | xargs rmmod -f

Then add the following to /etc/nixos/configuration.nix:

boot.supportedFilesystems = [ "zfs" ];

And rebuild the system:

nixos-rebuild switch --upgrade

Partition the disk:

parted --script /dev/nvme0n1 -- mklabel gpt mkpart esp fat32 1MiB 512MiB mkpart primary 512MiB 100% set 1 boot on

Create an encrypted pool. The -O flags set filesystem properties that every dataset inherits, so they only need to be given once here:

zpool create -f \
    -o ashift=12 \
    -o autotrim=on \
    -O encryption=on -O keyformat=passphrase \
    -O compression=zstd \
    -O dnodesize=auto \
    -O xattr=sa \
    -O acltype=posixacl \
    -O relatime=on \
    -O redundant_metadata=most \
    -O mountpoint=none \
    rpool /dev/nvme0n1p2

Create the datasets. Keeping /nix separate from / means the store can be excluded from snapshot and rollback policy, which is what makes an erase-your-darlings setup possible later:

zfs create -o mountpoint=legacy rpool/root
zfs create -o mountpoint=legacy rpool/nix
zfs create -o mountpoint=legacy rpool/home
zfs create -o mountpoint=legacy -o recordsize=1M rpool/Storage
zfs create -o mountpoint=none -o refreservation=2G rpool/reserved

Mount them:

mkdir -p /mnt
mount -t zfs rpool/root /mnt
mkdir -p /mnt/nix /mnt/home /mnt/Storage
mount -t zfs rpool/nix /mnt/nix
mount -t zfs rpool/home /mnt/home
mount -t zfs rpool/Storage /mnt/Storage

Why these properties

Some of these can only be chosen when the pool or dataset is created, so they are worth getting right the first time.

Creation-only, no way to change later without recreating the dataset:

  • encryption and keyformat enable native ZFS encryption. This cannot be turned on afterwards.
  • dnodesize=auto allows dnodes larger than 512 bytes. Combined with xattr=sa this keeps extended attributes inline instead of spilling into separate blocks, which matters for a Nix store holding a hundred thousand small files. Existing files keep whatever size they were written with.
  • ashift=12 matches the 4K physical sector size of modern NVMe drives.

Changeable later, but only applied to newly written blocks:

  • compression=zstd gives a better ratio than the lz4 that plain compression=on selects. The Nix store compresses particularly well.
  • acltype=posixacl is needed for systemd-journald to grant journal access through ACLs. With the default of off that mechanism silently does nothing.
  • redundant_metadata=most reduces the number of duplicate metadata writes.
  • recordsize=1M suits bulk file storage. Leave it at the 128K default for general purpose datasets, and drop it to 16K for databases or VM images.
  • autotrim=on issues TRIM continuously. The zpool-trim.timer unit that NixOS enables covers this periodically instead, so either approach works.

The rpool/reserved dataset never gets mounted. Its refreservation holds space back so that the pool can be brought below its full mark by destroying that one dataset. ZFS performance degrades noticeably above roughly 80% capacity.

On a single disk pool there is no redundancy, so ZFS can detect corruption but never repair it. Setting copies=2 on the datasets that hold irreplaceable data stores a second copy of each block at the cost of double the space:

zfs set copies=2 rpool/home

Snapshots are configured through services.sanoid in hosts/Common/zfs.nix. ZFS dataset names are case sensitive, so an entry there has to match the dataset exactly. A name that does not resolve leaves that dataset with no snapshots at all while the service still reports success.

Format the boot partition:

mkfs.fat -F 32 -n BOOT /dev/nvme0n1p1
mkdir -p /mnt/boot
mount -t vfat /dev/nvme0n1p1 /mnt/boot

Generate the configuration:

nixos-generate-config --root /mnt

Add the following to /mnt/etc/nixos/configuration.nix:

boot.initrd.supportedFilesystems = [ "zfs" ];
boot.supportedFilesystems = [ "zfs" ];
services.zfs.autoScrub.enable = true;

networking.hostName = "Aloria";
networking.hostId = "abcdef01";

Install

Then either clone the repository:

git clone https://git.thomasave.be/thomasave/Dotfiles
sudo nixos-install --impure --flake ./Dotfiles#Aloria
mv ./Dotfiles /mnt/home/user/.dotfiles
sudo ln -s /home/user/.dotfiles /mnt/etc/nixos

Or install it directly:

sudo nixos-install --impure --flake git+https://git.thomasave.be/thomasave/Dotfiles#Aloria

Post-install

Clean-up:

umount /mnt/{home,nix,Storage,boot}
umount /mnt

If using ZFS:

zpool export -a