Skip to content

plexctl key

Synopsis

plexctl key is the operator surface for the per-Node mesh-key rotation control plane. The family currently exposes a single rotate leaf that targets two operations on /v1/nodes/{id}/keys:

  • POST /v1/nodes/{id}/keys/rotate — record a rotation trigger (default).
  • GET /v1/nodes/{id}/keys/rotate/preview — fetch the impact preview without recording a new rotation (via --dry-run).
text
plexctl key rotate --node <uuid>          # record a rotation
plexctl key rotate --node <uuid> --dry-run  # preview only

A rotation re-issues the pairwise PSK on every live edge attached to the addressed Node. The signing-key rotation surface is a distinct aggregate — see Relationship to signing-key rotation below for the boundary.

Subcommands

plexctl key rotate

The leaf branches on --dry-run:

  • Default path — POSTs /v1/nodes/{id}/keys/rotate and renders the resulting rotation handle (rotation_id, node_id, state, requested_at). The server is idempotent on a pending row, so a second POST for a Node whose rotation is already pending returns 409 already_pendingexitCodeFor maps that branch to exit 0 so CI scripts can retry without false alarms.
  • Preview path (--dry-run) — GETs /v1/nodes/{id}/keys/rotate/preview and renders an impact summary: the addressed Node, the rotating Peer, the affected peer count, the already_pending flag and the estimated duration. The detailed per-edge listing is collapsed into the count for the text renderer; operators who need the full edge list select --output json or --output yaml.

The leaf does not wrap non-2xx responses with fmt.Errorf — the shared output.DecodeProblem helper returns a typed *output.APIError so the dispatcher's exitCodeFor can route the 409 already_pending branch to its dedicated exit code.

Flags

plexctl key rotate

FlagTypeRequiredDescription
--nodestring (UUID)yesNode UUID whose mesh keys to rotate.
--dry-runboolnoFetch the rotation impact preview without recording a new trigger.

Persistent flags inherited from root

--server, --profile, --token-file, --output. See ../plexctl.md for the canonical list.

Exit codes

See ../plexctl.md#exit-code-taxonomy for the inherited base table. The Problem.code branches that apply to this family:

HTTP statusProblem.codeExit code
409already_pending0 — the trigger is idempotent; a re-trigger is a no-op.
404node_not_found4
403rebac_denied77

Relationship to signing-key rotation

The plexctl key rotate family addresses the per-Node mesh-key that anchors WireGuard edges in a Domain mesh; the rotation is local to one Node and affects only the peers connected to that Node.

The plexctl signing family — introduced in the sibling Signing-Key Rotation work — addresses the per-Domain signing key that signs the event bus. The two rotations target different aggregates, use independent gRPC vs HTTP surfaces, and can run independently: rotating a Node's mesh key does not affect the Domain signing key and vice versa. The two CLI families exist side by side so an operator picks the verb (key rotate vs signing rotate) matching the aggregate they intend to touch.

Examples

Trigger a rotation

shell
export PLEXSPHERE_URL="${PLEXSPHERE_URL:-https://localhost:8080}"

plexctl key rotate \
  --server "${PLEXSPHERE_URL}" \
  --node   0190a8b8-b1c1-7b1b-8b1b-b1b1b1b1b1b1

Preview the impact without recording

shell
plexctl key rotate \
  --server "${PLEXSPHERE_URL}" \
  --node   0190a8b8-b1c1-7b1b-8b1b-b1b1b1b1b1b1 \
  --dry-run \
  --output json

Cross-references