Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

.nornir/viz-modes.md

nornir viz — mode resolution (fat · thin · server)

How nornir viz (and the three deployment modes) decide where the data comes from when you launch the visualizer. Decided with Rickard, 2026-06-12.

TL;DR

The resolution rule (what run_viz does)

In order:

  1. NORNIR_SERVER set → THIN (explicit override; unchanged).
  2. --warehouse <dir> given → FAT/embedded against that dir (explicit).
  3. Otherwise, is a workspace config found? — --config <path>, or config discovery walking up from cwd into a workspace_<name>/release/nornir.toml:

    • found → FAT/embedded (nornir-ui reads your ~/.nornir).
    • not found → THIN CLIENT: probe 127.0.0.1:7878; if a server is up, connect to it (a remote call) with the token from the user-readable ~/.nornir/token. If no server is reachable → an empty local view plus a hint (cd into a workspace, or start a server).

So "no config ⇒ thin" is the whole idea: if you haven't told nornir which workspace you mean, the most useful thing is to show the server's catalog.

The token

Thin mode needs a bearer token. Resolution: $NORNIR_SERVER_TOKEN, else the user-readable ~/.nornir/token (mode 600). nornir writes that file so a human who administers the box gets out-of-the-box thin access without sudo-reading /etc/nornir/nornir.env.

The three modes are EQUAL — add populates, the poll loop only updates

The fat user does exactly what the server does; the server just automates the "stay fresh" step.

what it does fat (you) server (nornir user)
workspace register <ws_X> (the add) record the workspace + its members from the descriptor ✅ same command ✅ same command
populate = fetch (clone members) + build → ~/.nornir/workspaces/<name>/builds/warehouse fill the warehouse so it's viewable ✅ you run it (fetch + a build) ✅ done on register/poll
poll loop automatically re-fetch + rebuild on a git HEAD change — the update path only ✗ (no daemon; you re-run on demand) ✅ the only server-extra

Design intent (target): make add eager — register → fetch → build inline so the warehouse is populated now (immediate feedback), and demote the poll loop to update-only (it watches git and re-runs the build on change). Then fat and server differ only in who pushes the update button — the poll loop is just the automated add/update.

Data lives under the home-derived root either way (see data-root.md): ~/.nornir/workspaces/<name>/ for you, /home/nornir/.nornir/workspaces/<name>/ for the server — same code, same shape.

Forcing a mode

Connect a viz client to a server (the full flow)

The end-to-end "I want to watch a server's workspaces" path:

# 1. On the SERVER host — install + run it (see running-as-a-server.md):
cargo install nornir --features viz          # → nornir, nornir-server, nornir-ui
sudo nornir install add --token <≥16-char-secret> --addr 0.0.0.0:7878
#   (`install` is idempotent + PRESERVES the token/ssh key across upgrades)

# 2. From ANY machine — point the viz at it:
nornir viz --server http://<host>:7878 --token <the-secret>

That's it — --server makes it a thin client (a plain gRPC call), so the picker shows all the server's workspaces. Switching the top picker re-scopes every tab live.

Every data-bearing tab fills from the server, not just Timeline/Warehouse: 🚀 Release (Viz.ReleaseEvents), 🏆 Leaderboard (Viz.BakeoffResults), 🗺 Knowledge (Viz.Knowledge — the server scans its cloned checkouts), 📡 Live Run (durable hydrate via Viz.ReleaseEvents + the Release.Progress live stream), 🗂 Funnel (Funnel.Show). The 🔗 Dep Graph derives from the Timeline, so it builds wherever Timeline does. The full tab → RPC → table map and the "why is a tab empty in thin mode" guide live in viz-remote-rpcs.md.

The token — how it's resolved

The bearer token (≥16 chars) is the app-level guard; every RPC carries it. nornir viz looks for it in this order:

  1. --token <secret> on the command line, else
  2. $NORNIR_SERVER_TOKEN in the environment, else
  3. ~/.nornir/token — a user-readable file (mode 600). Drop the secret there once and bare nornir viz (auto-thin) + nornir viz --server … both pick it up with no flags. (On the box that runs the server, the token is the secret you passed to nornir install; it also lives in /etc/nornir/nornir.env, readable only by root — so ~/.nornir/token is the convenient user-space copy.)

So: server admin chooses the secret at nornir install; clients get that secret (shared over a trusted channel / tailnet) and either pass --token, export NORNIR_SERVER_TOKEN, or save it to ~/.nornir/token.

See also: viz-remote-rpcs.md (the thin read path: tab → RPC → table, + adding a new remote-backed tab), running-as-a-server.md (install + run the server), howto-remote-collaborator.md (Tailscale remote access), mode-matrix.md (the full verb×mode contract), data-root.md (the ~/.nornir layout).