Skip to content

Federation

Federation links independent Pier cores. A primary core can pull a read-only view of its peers’ projects and stacks, and — when granted a token — deploy, restart and tear down stacks on those peers from one panel. Each core keeps its own database; federation is a control overlay, not a merged install.

Federation grants are Owner-only; the read and write surfaces below are admin-level actions.

A background scheduler polls every registered peer and refreshes a local cache of its projects and stacks. The sync runs roughly every 45 seconds (after a short startup delay), fetching projects and stacks from each peer’s normal read API and replacing the cached rows for that peer inside a transaction. A failed poll leaves the last-known data in place rather than blanking the cache, so the panel can show how stale a peer’s view is.

The cached, read-only view is exposed on the primary at:

  • GET /api/v1/federation/projects — local plus cached peer projects, tagged by source.
  • GET /api/v1/federation/stacks — the same for stacks, including whether each peer is paired for writes.
  • GET /api/v1/federation/status — per-peer sync bookkeeping (last sync, last error, consecutive failures).
  • POST /api/v1/federation/sync — trigger an out-of-band refresh instead of waiting for the timer.

Inter-core authentication uses federation tokens. On the peer, the operator mints a token (POST /api/v1/federation-tokens with a label); the plaintext is shown exactly once and stored only as a SHA-256 hash plus a short visible prefix. The operator copies it into the primary, which sends it on write calls in the X-Pier-Federation header.

Manage tokens on the peer at:

  • GET / POST /api/v1/federation-tokens — list and mint.
  • DELETE /api/v1/federation-tokens/{id} — revoke (a soft revoke that keeps the row for audit).

A federation token authorizes only the peer’s federation control surface — creating and managing the stacks the primary deploys. It cannot touch the peer’s users, sessions or admin settings, and it does not grant control over stacks the peer already owns itself.

With a token in place, the primary controls a peer’s stacks through passthrough routes that forward to the peer over the X-Pier-Federation channel:

ActionRoute (primary)
Create stackPOST /api/v1/federation/peer/{server_id}/stacks
DeployPOST /api/v1/federation/peer/{server_id}/stacks/{stack_id}/deploy
DownPOST /api/v1/federation/peer/{server_id}/stacks/{stack_id}/down
RestartPOST /api/v1/federation/peer/{server_id}/stacks/{stack_id}/restart
LogsGET /api/v1/federation/peer/{server_id}/stacks/{stack_id}/logs
ReleasePOST /api/v1/federation/peer/{server_id}/stacks/{stack_id}/release

On the peer, these land on a dedicated /api/v1/agent router gated by the federation token. Each stack created this way is owned by the issuing token: the peer enforces ownership, so one primary can’t manage another primary’s federated stacks, and releasing a stack returns it to the peer’s own panel without touching its running containers.

You can move a stack from the local core to a paired peer with POST /api/v1/stacks/{id}/migrate, passing the target server. Migration is limited to stateless Compose stacks — a stack with named or anonymous volumes is refused, since its data wouldn’t travel with it. The pipeline creates and deploys the stack on the target, then tears down the source and removes its local record.

DNS cut-over is not automated. Each server runs its own Traefik, so after a migration you re-point the stack’s domain to the new server yourself. The response returns the source domains as advice for exactly this step.