Skip to content

Rite of Resurrection — exampleHost

Complete guide to resurrect exampleHost from the ashes. Read this calmly before beginning — some steps are irreversible.

ComponentDetail
System disks2× Samsung SSD 980 PRO 1 TB NVMe (ZFS mirror)
ID disk 0nvme-Samsung_SSD_980_PRO_1TB_S5GXNL0W810368E
ID disk 1nvme-Samsung_SSD_980_PRO_1TB_S5GXNL0W810454N
Data disk/dev/disk/by-id/wwn-0x5000c500c78528e7-part1/data2 (ext4, nofail)
GPUAMD (driver amdgpu)
ZFS hostId21ed29b1

Note: /data2 is mounted with nofail — its absence does not block boot.

Before proceeding:

  • The exampleHost age key is available (Bitwarden, encrypted USB, paper backup…) See Reliquary Backup & Restoration
  • NixOS ISO is downloaded and burned/flashed Use a recent version: https://nixos.org/download/
  • The nixos git repo is accessible (GitHub or USB copy)
  • Network connection available (wired recommended for install)
  • If /data2 contains important data: back it up first

disko creates on each NVMe:

PartitionSizeRole
part11 GBESP (vfat)
part24 GBbpool (ZFS, grub2 mode)
part3920 GBrpool (ZFS)
part44 GBswap (random encryption)
part51 MBGRUB BIOS boot

ZFS datasets:

DatasetMountpoint
bpool/nixos/root/boot
rpool/nixos/root/
rpool/nixos/home/home
rpool/nixos/var/lib/var/lib
rpool/nixos/var/log/var/log

Flash the ISO to USB:

Terminal window
# From another Linux (replace /dev/sdX with correct device)
sudo dd if=nixos-minimal-*.iso of=/dev/sdX bs=4M conv=fsync status=progress

Boot from USB. Select NixOS in UEFI menu.

If wired: often automatic (DHCP).

If Wi-Fi needed:

Terminal window
sudo systemctl start wpa_supplicant
wpa_cli
> add_network 0
> set_network 0 ssid "MySSID"
> set_network 0 psk "MyPassword"
> enable_network 0
> quit

Verify:

Terminal window
ping -c3 github.com
Terminal window
# Clone into /tmp
git clone https://github.com/gfriloux/nixos /tmp/nixos
cd /tmp/nixos

If the repo is private or GitHub is unreachable, mount a USB with a repo copy:

Terminal window
mount /dev/sdX1 /mnt/usb
cp -r /mnt/usb/nixos /tmp/nixos
Terminal window
sudo nix run github:nix-community/disko/latest -- \
--mode destroy,format,mount \
--flake /tmp/nixos#exampleHost

disko will:

  1. Erase and repartition both Samsung NVMe
  2. Create ZFS pools bpool and rpool in mirror
  3. Create ZFS datasets
  4. Format ESP (vfat) and swap partitions
  5. Mount everything under /mnt

Verify /mnt is correctly mounted:

Terminal window
mount | grep /mnt
# Should display rpool/nixos/root, bpool/nixos/root, etc.
df -h /mnt /mnt/boot /mnt/home /mnt/var/lib /mnt/var/log

The age key must be present before NixOS activation for sops-nix to decrypt user passwords (neededForUsers = true).

Terminal window
sudo mkdir -p /mnt/etc/sops/age

Paste the saved private key content:

Terminal window
sudo nano /mnt/etc/sops/age/keys.txt

Expected format:

# created: 2024-01-01T00:00:00+01:00
# public key: age1xr32hdvanup0zk63v8hrcv2u2c09wplz6fd42w47mkjrd49j39xqaqqckq
AGE-SECRET-KEY-1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Correct permissions:

Terminal window
sudo chmod 640 /mnt/etc/sops/age/keys.txt
sudo chown root:root /mnt/etc/sops/age/keys.txt
# (tmpfiles will correct group perms on first boot)

Verify the public key matches:

Terminal window
nix run nixpkgs#age -- -y /mnt/etc/sops/age/keys.txt
# Must display: age1xr32hdvanup0zk63v8hrcv2u2c09wplz6fd42w47mkjrd49j39xqaqqckq

If the public key does not match, stop and verify the backup before proceeding.

Terminal window
sudo nixos-install --flake /tmp/nixos#exampleHost --no-root-passwd

The --no-root-passwd option avoids interactive root password setup (the kuri password is managed by sops).

Installation takes several minutes (package download). If a sops error appears, it is likely the age key — return to step 5.

If network error interrupts the download, re-run the same command: nixos-install resumes where it stopped.

Terminal window
sudo reboot

Remove the USB at restart. System should boot into GRUB → NixOS.

If GRUB does not appear: verify boot order in BIOS/UEFI. Look for “UEFI OS” or the Samsung NVMe names.

At first boot, these start automatically:

  • sddm (Plasma 6 login screen)
  • Tailscale (daemon, not yet connected)
  • pipewire, NetworkManager, Docker

Log in with user kuri and the password from sops.

Tailscale is running but not yet authenticated.

Terminal window
sudo tailscale up

An authentication link appears. Open it in a browser, log into Tailscale, approve the machine.

Verify connectivity:

Terminal window
tailscale status
# exampleHost should appear with a 100.x.x.x address
# Test access to clochette
tailscale ping clochette

If the old exampleHost entry remains in Tailscale admin with “offline” state, delete it from https://login.tailscale.com/admin/machines before re-enrollment.

Step 9 — First Deployment from Repository

Section titled “Step 9 — First Deployment from Repository”

Once Tailscale is active and the repo is cloned on the machine:

Terminal window
cd ~/Apps/github/gfriloux/nixos # or wherever the repo lives
just install

This (nh os switch .) applies the complete configuration and activates Home Manager. Re-run it whenever the config changes.

Terminal window
# ZFS pools are healthy
zpool status
# Should display ONLINE for bpool and rpool, no errors/degraded
# Secrets decrypted correctly
ls /run/secrets/
# Should list system secrets (e.g., users/kuri/hashed-password)
ls /run/user/1000/secrets/
# Should list HM secrets (rbw_server, workspace...)
# Docker operational
docker info | grep "Storage Driver"
# Should display: Storage Driver: zfs
# Tailscale
tailscale status
# AMD GPU
glxinfo | grep "OpenGL renderer"
# Should display an AMD renderer (e.g., AMD Radeon RX...)

If one or both Samsung NVMe are replaced with new models, the IDs in systems/x86_64-linux/exampleHost/disko.nix and boot.nix will no longer match.

Before reinstalling, update the IDs:

Terminal window
# From ISO, identify new disks
ls -la /dev/disk/by-id/ | grep nvme

Update disko.nix and boot.nix with the new IDs, commit, then resume at step 4.