nordisk-pairing 0.5.2

The boxes of an estate find each other: a seed each box is installed with, a one-time join against the front, a tunnel (WireGuard by default) they meet inside, roles decided once, a pairing loop each box runs itself, and the signal it reports. Shared by gunnar and holger; the laptop's xtask only lays machines, writes seeds and reads the signal. Design: .nornir/pairing-design.md (2026-09-24).
Documentation

The boxes of an estate find each other.

Until 2026-09-24 the laptop's xtask was the matchmaker of the gunnar.rs estate: three machines booted knowing nothing of each other, and every introduction — bootstrap the primary with the front's console key, enrol the principals, confer the twin's role, sign its certificate — was one ssh command from a laptop, run once, in order. Every one of them was a place the chain broke (a box not listening yet, a killed run, a dropped packet), and a laptop in the middle of an installation is a single point of failure that has nothing to do with the estate.

The owner's order (2026-09-24): the xtask does not pair. It starts the machines with enough information for them to form a tunnel — WireGuard by default; Tailscale, Mullvad, or none — and the boxes pair each other inside it. gunnar and holger share this crate. Design: Skidbladnir/.nornir/pairing-design.md.

The pieces, in the order a box meets them:

  1. [seed] — what a MEDIUM is told at compose time, the same for every lay: the estate, the tunnel kind, the join door's fixed address, the installer CA and the bootstrap certificate. Nothing per box, nothing per lay — the medium is constant (2026-09-24 evening).
  2. [tunnel] — the driver trait and the none driver. Only the FRONT needs a known address; the others dial it, and the overlay addresses are ours.
  3. [join] — the one-time join against the front's door over mutual TLS: the box presents its tunnel public key and its capacity; the door admits it by the address it joins from, and answers with its name and overlay address, the peers (the front's tunnel first), the role, and the FEED.
  4. [elect] — the weakest gunnar box becomes the twin, decided ONCE on the front from two capacity reports, never re-decided.
  5. [pair] — the state machine each box runs: tunnel up → joined → role known → paired, every step idempotent and retried by the box itself.
  6. [signal] — where a box is, as one line and as a value; what the xtask (and an operator) READS instead of doing.

Pure Rust, no shell (LAW). No driver here ever answers "up" for a tunnel it did not bring up: none and wireguard work, mullvad works as each box's EXIT beside the WireGuard mesh, and tailscale refuses by name ([tunnel-tailscale-unimplemented]) — see [tunnel].