github nasty-project/nasty v0.0.8
NASty v0.0.8

4 hours ago

This is the nginx → Caddy migration release. The reverse proxy and TLS terminator under the WebUI moved from nginx to Caddy. ACME issuance is now driven directly through Caddy (lego dropped), per-app ingress applies at runtime via Caddy's admin API, and the v0.0.7 NetworkManager compatibility scaffolding has been removed — boxes upgrading from 0.0.7 should be reconciled before jumping. Anything still on 0.0.6 or earlier should pass through 0.0.7 first.

Headline changes

  • Caddy replaces nginx as the reverse proxy and TLS terminator. App ingress routes apply through Caddy's admin API at install / remove time — config changes take effect in-process with no file rewrite and no reload. TLS automation is one atomic admin-API PATCH per change, so per-host issuance state shows up live on the TLS page.

  • Per-app subdomain ingress (V1 of #99). Apps can now be served at app.example.com instead of (or alongside) /apps/<name>/. Subdomain mode is selectable at install time and editable later, conflicts are detected before submit, and ingress-incompatible apps (whose absolute-path assets break path-prefix mode) auto-detect themselves and surface a clear reason in the install UI.

  • Self-signed certs now cover both nasty.local and the box's LAN / Tailscale IPs. Direct-IP HTTPS (https://10.x.x.x) validates the cert against the IP directly — only the "untrusted CA" warning remains, which clears once you import Caddy's root via the Download CA Root button on the TLS page. Unknown SNI (tailnet *.ts.net names, anything not on the cert) falls back cleanly to the internal cert.

  • Files page learned copy, move, and bulk actions (#88). Per-row Copy / Move icons + multi-select bulk action bar (Copy / Move / Delete) using the existing PathPicker. The same dialog handles files and directories regardless of which bcachefs pool the destination lives on.

  • NetworkManager compatibility scaffolding from v0.0.7 has been removed. The legacy networking layer, the one-shot migration cutover, and the Phase-X comments are gone. A clean reconcile of orphan interfaces + NM profiles runs at startup, per-connection NM apply errors surface individually in the UI, and DBus type encoding for MAC / DNS fields aligns with what NetworkManager expects.

TLS / reverse proxy

  • ACME automation driven directly through Caddy — lego dropped, the entire TLS pipeline lives in one process.
  • Nine DNS-01 plugins compiled in (Cloudflare, Route 53, Hetzner, Linode, Porkbun, Namecheap, DuckDNS, deSEC, RFC2136); per-provider directive emitter on the engine side.
  • DNS-01 challenge knobs in Settings → TLS: propagation_delay (default 30s) and external resolvers (default 1.1.1.1, 8.8.8.8) — useful for split-horizon DNS, restricted egress, or providers with aggressive negative-TTL caching.
  • Per-host issuance state on the TLS page: per managed name, issuing / active / failed / pending with the verbatim Caddy log line on failure.
  • Cert directory polled after admin-API push, so the UI flips to Active as soon as Caddy lands the cert.
  • WebUI exposes Caddy's local-CA root via a Download CA Root button — import once on each client to trust every per-name cert the internal CA issues.
  • Caddy version pinned at build time for reproducible upgrades.

Apps & ingress

  • New Ingress overview page — every Caddy route in one place (host / path / catch-all, handler kind, upstream, per-row cert status for host-match routes).
  • "Subdomain" menu is always present at install time; subdomain ingress survives reboots even for apps whose path-prefix mode was auto-disabled.
  • Subdomain conflict detection before submit.
  • Compose apps persist ingress_subdomain reliably across restarts (#247).
  • Auto-detect apps whose absolute-path assets break path-prefix ingress; engine sets proxy_disabled_reason with a human-readable explanation, honoured on reconcile after restart.
  • Curated sub-path recipes for Grafana and Vaultwarden — known-working env presets at install time.
  • Idle-poll apps.list so containers crashing or installs from another tab show up without a refresh.
  • Image inspection fetches registry tokens for ghcr.io and quay.io alongside Docker Hub.
  • Docker-paste button on the Apps install form (paste a docker run … and the form fills itself out).
  • Treat docker named volumes as auto-managed; tag image-default env vars so Edit can grey them out and only highlight values the operator set explicitly.
  • Shell button surfaces exec_command errors directly when invocation fails.
  • App install / remove robustness: real-world fixes from the Haze launch — better error reporting, idempotent re-install paths.
  • Live per-app apps.stats rewritten for one Docker round-trip per frame; the Apps page renders stats instantly on load.
  • Deploy WS close verifies app state before reporting failure — transient blips during docker create_container resolve correctly once the container reports up (#208).
  • Port form on the Create/Edit dialog reads Name | Exposed | Internal left-to-right, matching docker run -p HOST:CONTAINER and every other UI in the ecosystem (#271).

Files

  • Copy, Move, and Bulk actions on the Files page (#88). Per-row Copy / Move icons, sticky bulk action bar (Copy / Move / Delete / Clear) when one or more rows are selected, select-all checkbox with indeterminate state.
  • Cross-filesystem copy works natively — operators can move data between bcachefs pools mounted under /fs without dropping to a shell.

Subvolumes

  • Per-row Usage column engine-side (closes #81) — one snapshot of who owns what (NFS, SMB, iSCSI, NVMe-oF, apps, VMs, backup jobs) per subvolume, batched in a single RPC.
  • Cascade-delete dialog — deleting a subvolume that backs an iSCSI target / NFS share / SMB share / NVMe-oF subsystem now lists what's in use and offers a single "Delete subvolume + N dependents" button. Apps / VMs / backups are surfaced with a direct link to their lifecycle page so cleanup stays explicit.
  • Detail pane surfaces Apps and VMs as subvolume consumers — same dependency tree the Usage column reads.

UPS / NUT

  • Remote NUT server mode. NASty can now monitor a UPS attached to a different box (Synology, another NASty, a standalone NUT server) over the network — no USB-attached UPS required on the appliance itself.

Networking

  • v0.0.7's compatibility scaffolding removed: legacy networking layer gone, one-shot migration cutover gone, stale Phase-X / cutover comments stripped.
  • Orphan interface + NM profile reconcile at startup — removed bridges / bonds get their NM profiles and sysfs interfaces cleaned up automatically.
  • NM MAC fields encoded as DBus byte arrays, NM DNS fields encoded as the correct family-specific DBus type — apply paths align with what NetworkManager expects.
  • Per-connection NM apply errors surface individually in the WebUI for targeted troubleshooting.
  • Discovery daemons (samba-wsdd, avahi-daemon) restart on every network apply, so newly-added bridges / bonds / VLANs stay visible in macOS Finder, Windows Explorer, and Linux file managers (#270).
  • Network form validates IP / CIDR before submit (#202).

Backups

  • S3 backup profile create form exposes the region field (#212).
  • Backup profile forms expose SFTP port and retention keep_yearly (#213).

System & updates

  • nasty-top bumped to 0.0.5 — tuning advisor now shows HINT lines with reasoning instead of one-key-apply suggestions; device error counts are session-aware (pre-existing counts dim, only growth highlights bold red); Ctrl-C quits from any mode; device list grouped by label and natural-sorted (sda1 < sdz1 < sdaa1, nvme0n1 < nvme10n1).
  • Glossary additions: Caddy and Audit Log entries on the Help page.
  • openssl and uv / uvx now on PATH — cert inspection, TLS handshake debugging, and Python-tool one-shots work directly from the box's shell.

Engine reliability

  • State-file handling preserves data on parse failure. Eight state files (auth.json, settings.json, alerts.json, nut.json, tailscale.json, passthrough.json, tuning.json, rate-limit.json) now back the existing file up as .corrupt.<unix-ts> before falling through to defaults, log a warning, and continue — so a malformed JSON stays recoverable instead of being overwritten.
  • Engine startup is robust to slow / unreachable OIDC IdPs and Caddy admin APIs — both moved to background spawns with bounded retry budgets, so the engine reaches ready state quickly regardless of upstream latency.
  • Audit log coverage expanded: permission_denied on role-denied RPCs, terminal_opened / vm_console_opened / log_stream_opened on privileged WebSocket opens, and unsafe-deploy entries carry the actual admin's username.
  • Six engine paths gained observable warning logs when subprocesses like bcachefs, losetup, blkid, or stat surface errors — the journal now explains what fell back to defaults instead of swallowing the cause.
  • WebSocket robustness: server-initiated ping/pong + exponential client backoff (#207); reconnect overlay debounced 800ms so the UI only signals real disconnects (#205).

CI / infrastructure

  • systemd-hardened nasty-engine and nasty-metrics: NoNewPrivileges, LockPersonality, RestrictSUIDSGID, ProtectClock, RestrictRealtime, KeyringMode=private, RestrictAddressFamilies on both; full Protect* namespace lockdown plus ProtectSystem=strict on metrics.
  • Workspace tests went from ~410 to ~440 — three previously-empty crate test harnesses (nasty-apidoc, nasty-backup, nasty-snapshot) gained meaningful coverage.
  • Cargo / npm / rnix / rowan all bumped to current.
  • HTTPS + WSS + security-header smoke assertions in the appliance-smoke CI; /apps/<name>/ ingress short-circuits the registry pull when the image is already local.

Bug fixes

  • Compose apps' ingress_subdomain was silently dropped on first set (#247).
  • PathPicker reverted to root on directory click (#252).
  • App deploy WS close mid-docker create_container no longer shows a false "Connection closed unexpectedly" modal (#208).
  • ACME issuance had two separate PATCHes (automation + automate) that could cancel each other mid-flight on rapid changes; collapsed into one atomic PATCH.

Proxmox users: NASty requires UEFI. Switch the VM firmware from SeaBIOS to OVMF before installing, otherwise NASty won't boot after the first restart.

Switch from SeaBIOS

to OVMF (UEFI)

Don't miss a new nasty release

NewReleases is sending notifications on new releases.