How it works
Bring your config
Your NixOS flake imports the nixnas module and sets a handful of nixnas.* values. Everything you actually run — services, containers, orchestrators, shares — is your own declarative NixOS.
Write your image
A local Rust TUI builds the personalised image on your machine, signs it with your own Secure Boot keys, and flashes the stick. Your secrets never leave.
Boot from RAM
Encrypted, headless, with a tmpfs root. Every disk needs your passphrase; TPM protects only the initrd SSH identity. A bad update? Boot the previous generation from the menu.
What nixnas does
Boot a Nix from USB, into RAM
From an 8 GB stick up. The root is a tmpfs (impermanence); only /nix and the ESP persist, and the closure is warmed into a compressed page cache — run-from-RAM without copytoram, updates intact.
Secure Boot, your keys
lanzaboote signs every Unified Kernel Image with your own PK/KEK/db. The Microsoft CA is not enrolled — no unsigned kernel runs. Paired with a firmware password and measured boot, it's evil-maid hardened.
Passphrase-only disks
The operator supplies a passphrase on every boot. No TPM token or auto-unlock path can release a disk key.
Headless remote unlock
No console? A per-device TPM-gated initrd SSH identity authenticates the channel for the mandatory passphrase. With no TPM, unlock locally or through IPMI.
Tuned for speed
The CachyOS kernel (x86-64-v3 + ThinLTO), pulled pre-built from a binary cache — performance without a local compile. f2fs zstd:22 keeps the slow stick small.
Declarative & rollback-safe
The whole appliance is your git-versioned NixOS. Every past generation stays bootable as its own signed UKI; the bootloader menu is the guaranteed rollback, with boot-counting on top.
Delivered updates, never self-reboots
Updates arrive through a nixdeploy receiver composed alongside nixnas. Nothing in nixnas reboots the box, so a headless box is never abandoned at a passphrase prompt.
Bring your own storage
Connect the storage you already have — any Linux filesystem and encryption. nixnas imports and unlocks it; it never creates, formats, or destroys it. The box boots even if a disk is missing.
Kind to the stick
Logs, /tmp, coredumps and swap live in RAM, so the USB takes ~no writes except updates — measured at 60 KiB for ~100 MiB of activity. Cheap sticks don't wear out.
Portable disks
Every disk carries a passphrase keyslot, so a disk pulled into another machine still opens. TPM protects only the remote unlock identity.
One passphrase, all your data
nixnas-unlock opens your LUKS members serially — the first entry is cached in the kernel keyring and opens the rest, imports the pools, and starts everything gated on them. One entry per boot, for the whole set.
Thin by design
nixnas owns boot, crypto, the USB store, and kernel packaging — nothing else. Your services, containers, k3s, shares, VMs — whatever you run — are your own NixOS, declared alongside.
Architecture
USB stick (8 GB+, write-isolated)
ESP signed UKIs - Secure Boot (your keys) + rollback
store LUKS2 + f2fs-zstd - the nix store = your OS
|
| unlock once: passphrase (local/IPMI or TPM-gated initrd SSH)
v
root = tmpfs (RAM) - /nix warmed into compressed RAM
|
+---> your declarative config in git (services, containers, k3s - you bring)
|
+---> your Linux storage (any FS + encryption; imported, never formatted)
Impermanence
The root is a tmpfs; only /nix and the ESP survive a reboot. The OS runs from RAM — the slow stick is spared, runtime state lives on your storage.
You bring the rest
nixnas is the boot + crypto + store + kernel mechanism. Your workloads — k3s, containers, file shares, VMs — are plain NixOS in your own git, built into the same image.
Import-only
nixnas unlocks and mounts your existing storage. It never creates, formats, or destroys it — the only device it ever partitions is the USB stick.
Get started
Scaffold your host
nixnas is the public core; your real disks, keys and config live in your own flake that imports it:
nix flake init -t github:corbet-nix/nixnas#host
Fill in your nixnas.* values in host.nix — storage, SSH keys, the USB device — and add whatever else you run as normal NixOS.
Write & flash your image
The Rust TUI builds the personalised image on your trusted machine and flashes the stick:
cd tui && cargo run
# → builds .#image, prompts the passphrase,
# flashes via caligula
Requirements
A UEFI x86-64 box with TPM 2.0, an 8 GB+ USB stick, and your own storage (any Linux filesystem; LUKS members carry the chosen passphrase as a keyslot). Secure Boot needs your own keys enrolled + a firmware password.
Status. The passphrase-only LUKS image, TPM-gated initrd SSH identity, rollback, and update paths are VM-tested. Real-hardware gates remain: owner-key Secure Boot enrollment, firmware setup-password enforcement, TPM credential bootstrap, and physical main/rescue boots. Signed-version anti-rollback is not claimed. See the architecture notes.