# Noust 3.0 changelog

Changes since WASM 2.3.0. Upgrade notes are in [UPGRADING-3.0.md](/docs/releases/upgrading-3.0/).

## 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](/docs/guides/fleet/).

## 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](/docs/guides/fleet/): running a central, adding a server, sealing its secrets,
  backups and troubleshooting.
