Skip to content
Pages in Releases

Noust 3.0 changelog

What changed in 3.0.

Reference Updated View as Markdown

Changes since WASM 2.3.0. Upgrade notes are in UPGRADING-3.0.md.

WASM is now Noust

"WASM" means WebAssembly to every search engine, package index and command line, which kept the project from being found. 3.0 renames it. In Orkney and Shetland, a noust is the hollow on the shore where a boat is drawn up and sheltered between voyages: your server is the noust, your applications the boats.

  • The command is noust. wasm runs the same program for the whole 3.x series, so no operator script or cron line breaks on the upgrade; typed at a terminal, it says once that the product is now Noust. noust --version prints "Noust X (formerly WASM)".
  • Packages: noust on PyPI and in the home:Perkybeet repository for apt, dnf and zypper. wasm (Debian, Ubuntu) and wasm-cli (Fedora, openSUSE, PyPI) are empty transitional packages that depend on noust, so the usual upgrade command brings it in. The default configuration ships as a reference at /usr/share/noust/config.example.yaml.
  • Paths: /etc/noust, /var/lib/noust (the store is now noust.db), /var/backups/noust, /etc/nginx/noust-upstreams and ~/.local/share/noust. Noust's own logs go to /var/log/noust; /var/log/wasm is left as it was.
  • noust migrate-from-wasm moves a WASM server onto the new names: each directory with one atomic rename on the same filesystem and a symbolic link at the old name, the store renamed after a checkpoint and never recreated, WASM's default paths in config.yaml updated, blue/green includes and PHP-FPM pools renamed behind nginx -t without dropping a request, and Noust's own units replaced one at a time, each put back if its replacement does not come up. It runs from the packages' upgrade and on the first command run as root (not inside a systemd unit, under --dry-run, or with NOUST_NO_AUTO_MIGRATE=1), and can be interrupted and run again. --dry-run shows the plan, --json reports for scripts.
  • Noust's own units are noust-web, noust-monitor, noust-cron-*, noust-backup-* and noust-previews, marked "Generated by Noust"; units marked "Generated by WASM" are still recognised.
  • Application units do not change: <app_name>.service, including the wasm- prefix of units deployed before WASM 0.14.1. Nor do application directories, sites, domains, certificates, backups, the API, tokens, sessions or two-factor enrolment.
  • Environment variables: NOUST_* first, WASM_* still read.
  • API: new API tokens start with noust_tok_ and a new master token with noust_; tokens issued by WASM keep working. /health reports noust-web. GET /api/services takes noust_only (wasm_only still read). The session reports renamed_from_wasm. Cookies, the CSRF header and the WebSocket subprotocols keep their wasm names.
  • Repositories may name their nginx overrides noust.nginx.yaml; wasm.nginx.yaml is still read.
  • The console is called Noust: a new logo, favicon, titles and texts, in English and Spanish, and a notice, once per browser, on a server that ran WASM.
  • The Python package is noust; the repository is github.com/Perkybeet/noust.

The fleet

3.0 brings the fleet: one Noust, the central, shows and drives several other Noust servers from a single console and CLI, over SSH tunnels it opens outward, so nothing has to be opened on theirs.

  • Enrollment is inverted. noust fleet authorize --central-key ... --name ... runs on the server, as root, and prints a join code; noust node add NAME --ssh ... --join-code - on the central pastes it back. The central never logs in to a server with your credentials.
  • Every server's own API, proxied, not reimplemented. /api/nodes/{node}/api/..., /api/nodes/{node}/events and /ws/nodes/{node}/... forward to the node's own endpoints, event stream and WebSockets over its tunnel, so a node's error, its journal output and its events reach the console exactly as they are.
  • The console gets a server selector (every page also exists at /n/<server>/..., so a link survives a refresh), a Fleet page listing every node with its reachability, version and counts of applications, failed units and certificates due, and Settings > Servers to add, test and remove one.
  • Version differences. A node's own OpenAPI document tells the console what it can do, so a server on an older Noust degrades gracefully instead of a page failing outright.
  • noust fleet status, noust node list|show|test|remove.

The central

  • Role. central.role is server (the default: manages the fleet and deploys its own applications too) or hub (manages the fleet only; applications, sites, certificates and databases are refused there with a message, and the console hides them).
  • A container, for a NAS or any Docker host. ghcr.io/perkybeet/noust runs noust central run: the console and the tunnels, nothing else, as an unprivileged user with a read-only root filesystem and no capabilities. It serves TLS on 8443 (self-signed at the first start, unless you mount your own certificate) and keeps everything under /data. Reachable only from loopback and the private address ranges by default (NOUST_ALLOW_IP). packaging/container/compose.yaml is a ready example, including for UGOS Pro.
  • A VPS runs a central the same way as any other Noust: noust config set central.role hub turns off local deployment, and noust web enable serves its console as always.
  • noust central run|status|seal|unseal|unlock.

See docs/CENTRAL.md.

Security

  • The central's key on a server can only forward that server's console port. No shell, no agent, no command but a forced one that always fails; permitlisten closes the one direction port-forwarding reopens, a reverse tunnel an attacker could otherwise bind to loopback.
  • Fleet tokens are accepted only from loopback (the tunnel), and only a request presenting one may carry X-Noust-Actor, so a node's audit log names the operator behind the central, not just the central's name.
  • Elevation is the node's call. A node marks what needs sudo mode with its OpenAPI's x-noust-requires-elevation; the central asks its own operator to confirm before forwarding such a call, and the node refuses it anyway if the central did not vouch for it.
  • Host keys are pinned, not trusted on first use every time: a server's key changing closes the tunnel and says why.
  • A central's secrets can be sealed at rest (noust central seal): node keys and tokens encrypted under a passphrase that is never written anywhere, so a sealed central starts locked and opens no tunnel until it is given the passphrase.
  • A central refuses to add its first server without two-factor authentication turned on.

Also

  • noust config set central.role hub|server.
  • The GHCR image is new in 3.0.0: nothing in WASM published a container.
  • docs/CENTRAL.md: running a central, adding a server, sealing its secrets, backups and troubleshooting.

Something on this page is wrong or unclear? Report it on GitHub.

Help, contributing and the project’s policies are under Project.

Search the documentation

Type to search every page.

↑ ↓ to move, Enter to open, Esc to close