nixnas

Your declarative NixOS — secure, RAM-resident, on a USB stick

nixnas packages your own NixOS config into a USB-bootable appliance: it runs from RAM, locks the boot chain end to end, self-updates with rollback, and connects to the storage you already have. You bring the declarative config — a local TUI writes your signed image.

nixnas — write your image, boot from RAM
$ nixnas                       # a local TUI over your own flake
[nixnas] LUKS passphrase: ********   (RAM-backed 0600 file, shredded after the build)
[nixnas] building .#imageScript — CachyOS kernel · LUKS f2fs-zstd store · lanzaboote-signed UKI
[nixnas] ✓ nixnas.raw  — your config, ~3.4 GiB, zstd-compressed on the stick
[nixnas] flashing → /dev/disk/by-id/usb-…

$ # boots reachable, data still locked — one passphrase over SSH:
$ ssh root@box nixnas-unlock   🔐 passphrase: ********
[  OK  ] store: TPM2 · /nix on f2fs zstd:22 · root = tmpfs (RAM)
[  OK  ] your storage unlocked + imported + mounted — never formatted
box login: _

How it works

1

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.

2

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.

3

Boot from RAM

Encrypted, headless, running entirely in RAM. The stick unlocks via TPM2; your data waits for ONE passphrase over SSH (nixnas-unlock). 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, self-update 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.

TPM2 store unlock

The store key is released only when the boot chain measures clean — optionally plus a PIN on every boot (strict default; auto-unlock is the unattended-NAS choice). A mandatory recovery keyslot is the fallback.

Headless remote unlock

No console? The box boots reachable with the data locked; nixnas-unlock over SSH opens everything. With the strict PIN, the initrd itself runs sshd — validated unlocking the box entirely over the network.

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.

Self-update, never self-reboots

autoUpgrade stages the next generation and stops — it activates on your next PIN-unlocked reboot, so a headless box is never stuck at an unlock 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

Only the stick binds to the TPM. Your data carries a plain passphrase keyslot, so a disk pulled into any machine still opens — no specific box's TPM required.

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:  TPM2 + PIN  (headless, over SSH in the initrd)
       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:julian-corbet/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. Built and validated end to end in a VM (QEMU / OVMF / swtpm): the CachyOS kernel, impermanence, the LUKS f2fs-zstd store, lanzaboote Secure Boot, TPM2 + PIN, headless initrd-SSH unlock, rollback and self-update all boot in one image. Hardware bring-up — Secure-Boot key enrolment on real UEFI, the boot-counting bless loop, the firmware password and the TPM2-NV anti-rollback counter — is the next step. See the architecture notes.