This is the Secure Boot + Passkeys release. Boxes can opt into a Secure Boot–enforcing boot chain (lanzaboote) with a guided enrollment ceremony, TPM2-sealed bcachefs encryption keys, and WebAuthn sign-in via passkeys. The v0.0.8 nginx → Caddy migration scaffolding has been removed — boxes upgrading from v0.0.7 should pass through v0.0.8 first.
Headline changes
-
Per-box Secure Boot opt-in. New
nasty.secureBoot.enableflag wires in lanzaboote as a conditionally-imported sub-module so non-SB boxes pay zero cost. The Hardware page gains a readiness checklist (RPC + UI) showing whether the box can host SB, and an experimental enrollment ceremony wizard that walks operators through Phase 1/2 with a Rebuild button and accurate Abort copy. SB state is read viabootctl(single source of truth, replacing the earlier sbctl probe), surfaced in the Hardware page, andkexecis disabled once a box is SB-enrolled. Firmware-apply gracefully refuses with a documented reason when SB is enforcing (lanzaboote#591 incompatibility). Documented end-to-end in ADR 0001. (#323, #324, #325, #326, #331, #333, #335) -
WebAuthn / passkeys for sign-in (#289). Three-PR landing: credential registration and self-management so any user can manage their own keys (#327), sign-in alongside password (#328), and safeguards — operators can require a fallback factor on accounts that have keys, and admins can reset another user's WebAuthn credentials (#329). Origin precheck so HTTP / wrong-host / direct-IP access fails legibly instead of erroring out of WebAuthn's own validator. WebUI:
/accountfolded into Access Control; Users page split into Users & Groups / Tokens & Keys / Single Sign-On tabs. -
TPM2-sealed bcachefs encryption keys (#102).
storage: seal bcachefs encryption keys to TPM2lands the storage half (#287);webui: bind/unbind encryption keys to TPM2lands the UI (#290);fs.create: optional bind_to_tpm flaglets operators seal in one step at filesystem creation rather than create-then-bind (#320). Hardware page now reports TPM2 presence, vendor info viatpm2_getcap(#284), and capability detection (#283). -
Reliable upgrade flow end-to-end. Engine self-reports its own build commit as "current version" — no more
/run/booted-systemlag where it pointed at the previous closure post-activation, looping the "Upgrade available" prompt (#315).version_switchruns the wrapper-shape migration first so legacy wrapper-flakes get migrated atomically before any downstream version logic runs (#308, #313). Default upgrade flow refreshes only thenastyinput — won't drag along uncommitted nixpkgs / bcachefs-tools bumps (#293). Update page shows all three flake inputs with the GitHub lookup error surfaced if any one fails (#294). Half-applied upgrades bubble up through the WebUI instead of swallowing failures into the spinner (#292). Build-dir override collapsed behind a "recovery drawer" so it's there when you need it but invisible in the happy path; opt-in bcachefs build-dir spillover for small-rootfs installs (#295). -
Boot reliability. Per-phase boot timeouts and budgets sized to realistic worst case so one hung phase doesn't take the whole engine down (#300). New
system.boot_statusRPC and/api/boot_statusREST endpoint (#301); WebUI gets a booting overlay during startup and a post-boot health banner (#302). Encrypted-FS boot mount no longer hangs — bcachefs is probed for encryption before unlock (#305), and the storage layer distinguishes encryption-required from key-incorrect failure modes (#297).
Authentication & users
- WebAuthn credential registration and self-management (#289 PR #1, #327).
- WebAuthn sign-in alongside password (#289 PR #2, #328).
- WebAuthn safeguards — operator-required fallback factor; admin-side credential reset for locked-out users (#289 PR #3, #329).
- Origin precheck so IP / wrong-host / HTTP access fails legibly instead of breaking inside webauthn-rs's validator.
/accountpage folded into Access Control; security-keys controls live with the rest of access control.- Users page split into Users & Groups, Tokens & Keys, and Single Sign-On tabs.
Secure Boot
nasty.secureBoot.enabletoggle — per-box opt-in. Lanzaboote module imported conditionally so non-SB closures stay lean (#325).- Readiness probe (
system.secure_boot.readiness) + Hardware-page checklist (#326). - Enrollment ceremony wizard (experimental, marked as such in the UI) with Rebuild button and accurate Abort copy (#331).
- SB state read via
bootctleverywhere (replaces the earlier sbctl probe) (#323). kexecdisabled on SB-enrolled boxes; documented in the SB glossary.- Firmware apply refuses cleanly under enforcing SB with an operator-readable reason — engine-owned string consistent across banner, tooltip, and defensive RPC refusal (#333).
- Inline manual-unenroll recipe and glossary entries documented.
TPM2
- Capability detection on the Hardware page (#283).
- Vendor info populated from
tpm2_getcap(#284). - bcachefs encryption keys sealable to TPM2 (#102, #287).
fs.createacceptsbind_to_tpmfor one-step sealing at filesystem creation (#320).- Bind / unbind from the WebUI Filesystems page (#290).
nasty-enginehaskeyutilson PATH and the TPM2 TCTI pinned (#296).
Update flow
- Engine self-reports its build commit as current version — no
/run/booted-systemlag (#315). version_switchruns the wrapper-shape migration first (#308, #313).- Default flow refreshes only the
nastyinput (#293); the three-input view explains exactly what's being touched (#294). - Per-input GitHub lookup errors surface individually on the Update page (#294).
- Half-applied upgrades bubble up through the WebUI (#292).
- Build-dir override behind a recovery drawer; opt-in bcachefs build-dir spillover for small-rootfs installs (#295).
wrapper-flaketemplate:nixpkgs+bcachefs-toolsfollownasty(#304); canonical no-placeholder shape; explicit forward-compat shim that keeps the@BCACHEFS_TOOLS_REF@mention even when the active template doesn't use it (#317).version_switchpreserves the operator's bcachefs pin across rebootstrap.- bcachefs-tools back to an independently-pinned flake input; UI hides nixpkgs from the "what to bump" surface — it follows automatically (#312).
nasty-syncCLI: engine-bypass recovery + state inspection (#314);-rrescue mode + auto-detach when run from a WebUI terminal (#316);-n <ref>flag for switchingnasty.url's tracked ref (#318).
Boot reliability
- Per-phase boot timeouts and worst-case budgets (#300).
system.boot_statusRPC +/api/boot_statusREST endpoint (#301).- WebUI booting overlay + post-boot health banner (#302).
- Encrypted-FS boot mount hang fixed; login-failure vs encryption-missing distinguished (#297).
- bcachefs encryption probed before unlock attempt (#305).
nasty-engine:keyutilson PATH; TPM2 TCTI pinned (#296).- Unmount preserves tuned per-FS mount options so remount doesn't silently reset them (#298).
Telemetry
- Engine reports
version(semver),commit(short SHA),vms,apps, andarchalongside the existing drives / capacity / used fields (#334). - Worker schema, validators, and dashboard updated; new "Versions" and "Architecture" breakdown panels group commits under their semver as
<version>+. - Telemetry rows retained indefinitely — instances going silent no longer wipe their history at the 30-day mark, so historical peaks remain visible on the chart.
VM
Operational / DX
- Aggressive RPC reconnect during Update — the spinner clears in seconds instead of waiting on the default backoff (#322).
- WS reconnect recovers from silent TLS-reject after self-signed leaf rotation (#309).
system.log.level: live log filter reported back to the WebUI.- Caddy install no longer tries to install its internal-CA root into the OS trust store.
- systemd-boot menu label uses
nasty-version. - Router classifies
*.statusRPCs as read-only — avoids the refresh-loop on event-bus broadcasts that used to keepisBusy()blinking on the Filesystems page (#306). - memtest86+ as a systemd-boot menu entry (x86 only — aarch64 boxes skip the entry, no rebuild breakage) (#330, #332).
Removed
- nginx → Caddy migration paths. v0.0.8's reverse-proxy migration scaffolding is gone — both the engine cutover code and the lego → Caddy-ACME migration (#307). Boxes on v0.0.7 should pass through v0.0.8 first.
Build / CI
- Wrapper-flake template included in engine Nix
src; gated on Nix engine build pre-merge (#310). - Installer-template check inverted to enforce the no-placeholder shape (#317).
flake.nixoverlay sends an identifying User-Agent on everyfetchurlsocrates.io's enforcement of its crawler policy doesn't block PRs that introduce new crate versions (#337). Temporary until NixOS/nixpkgs#512735 propagates andimportCargoLockgets the same fix.- Weekly nixpkgs bump (#319).
nasty-enginederivation:pkg-config+openssladded (transitively pulled bywebauthn-rsviaopenssl-sys).
Proxmox users: NASty requires UEFI. Switch the VM firmware from SeaBIOS to OVMF before installing, otherwise NASty won't boot after the first restart.
![]()
⬇
![]()

