Skip to content

cli: single-artifact peer lifecycle for non-clan deployments #23

Description

@fosskar

Problem

Since 0.7.0 (#22) the engine handles membership changes correctly — but only clan users get them ergonomically. Non-clan deployments manage the peer set by hand, and every change is a multi-step, per-machine dance:

Adding a machine: exchange age recipients out of band, edit recipients on every existing machine, run ssync ticket on one machine, ssync join on the new one, restart daemons.

Removing a machine (docs/setup.md "Removing a machine"): edit recipients on every remaining machine, remove data_dir/namespace everywhere, re-pair every remaining machine with a fresh ssync ticket / ssync join, restart. For N machines that is N config edits plus N−1 re-pairs.

Clan mode has none of this because clan.vars owns the whole peer set: recipients, shared namespace secret (rotated via validation.peers), node-ids. The gap is purely UX/orchestration — the engine mechanism (recipient-fingerprint re-publish, drop_stale_replicas) is already in place.

Constraints

  • Leaderless (DECISIONS §4), no server (§6) — no coordinator to hold the peer set.
  • iroh-docs write capability is the namespace secret, so eviction always requires out-of-band redistribution of a new secret. Fully automatic in-band revocation is impossible by construction; the floor is "one artifact reaches each remaining machine, one restart".

Proposed direction (needs a call)

Promote shared-namespace mode to the primary manual mode and collapse membership into one distributable artifact:

  • ssync cluster init — generate a cluster file: shared namespace secret + recipient list (+ optional peer node-ids), same bytes on every machine.
  • ssync cluster add <recipient> [node-id] / ssync cluster rm <recipient> — rewrite the artifact; rm also rotates the namespace secret inside it.
  • The user distributes the updated file however they already move secrets (scp, sops-nix, USB) and restarts the daemon. Everything else is automatic: the changed recipient set triggers the fingerprint re-publish, the changed secret opens the new namespace, drop_stale_replicas abandons the old one.

That reduces any membership change to: run one command on one machine, copy one file, restart daemons. No ticket dance, no per-machine config edits.

Alternative (smaller, keeps ticket mode primary): a ssync revoke <recipient> helper that rewrites the local config, rotates the local namespace, prints the fresh ticket and the exact remaining steps. Cheaper, but stays O(N) manual actions per change.

Non-goals

  • No relay/coordination service, no automatic secret transport — distribution stays the user's channel.
  • No change to clan mode; ideally the cluster file is what the clan service generates, so both modes converge on one code path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-decisionDesign fork; needs a call before implementation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions