Skip to content

Servers & agents

A Pier core can manage more than its own host. You add a remote server as an agent — a lightweight, stateless daemon (pier-agent) that the core drives over a pinned HTTPS channel. The core stays the single control plane; the agent just runs Docker commands and reports metrics.

Adding, removing and deploying to servers are admin-level actions in the panel.

When you create an agent-kind server, the core mints a short-lived bootstrap token and hands you an install command. The script (served from GET /api/v1/servers/install-script) runs on the new host and:

  1. Installs Docker and the Compose plugin if missing, and creates the pier-net Docker network.
  2. Downloads the pier-agent binary from the core, authenticated with the bootstrap token.
  3. Installs pier-net-helper (dormant — it does nothing until the core sends a mesh op).
  4. Generates a self-signed TLS certificate for the agent and computes its SHA-256 leaf fingerprint.
  5. Performs the handshake, exchanging the one-shot bootstrap token for a long-term agent token.
  6. Confirms liveness with a first heartbeat.

The install script pins the core’s own self-signed certificate via curl --cacert, so the agent calls back over verified HTTPS rather than -k.

The bootstrap token is one-shot and short-lived. The agent spends it at POST /api/v1/servers/{id}/handshake, and the core mints the long-term agent token in response. That long-term token is returned exactly once and stored on the core only as a SHA-256 hash; the agent keeps the plaintext in its systemd environment file.

A second handshake against an already-redeemed bootstrap is rejected. If the install command leaked or was re-run, recreate the server in the panel to issue a fresh bootstrap — Pier won’t silently re-issue a credential.

Thereafter the agent authenticates every request with Authorization: Bearer <agent token>. You can rotate it from the panel (POST /api/v1/servers/{id}/rotate): the core pushes the new token to the agent first, and only persists it after the agent acknowledges, so a failed rotation never leaves the core out of sync.

The core-to-agent channel is HTTPS, but agents are reached by raw IP (or mesh IP) with no PKI chain. Instead of validating a certificate authority, the core pins the agent’s TLS leaf fingerprint — the SHA-256 the install script computed and sent during the handshake. Every subsequent core-to-agent call validates against that pin, so the channel is protected against certificate swaps. A re-affirmed fingerprint can arrive on a later heartbeat to re-pin after the agent regenerates its cert.

Once enrolled, an agent exposes:

  • Metrics — CPU, memory, disk, Docker version and container count, surfaced in the server card (GET /api/v1/servers/{id}/metrics, proxied to the agent’s /metrics).
  • Deploys — deploy or stop a Compose stack on the agent (POST /api/v1/servers/{id}/deploy and /stop). The core sends the rendered Compose YAML; the agent writes it under its data dir and runs docker compose.

The core also polls registered peers on a timer, while agents push their own heartbeat, so the panel reflects each server’s status.

An agent can be promoted into a full pier-core. The core exports a promotion bundle from its database and sends it to the agent (POST /api/v1/servers/{id}/promote). The agent writes the bundle, downloads the pier-core binary, imports the bundle into a fresh database, installs a systemd unit, stops pier-agent and starts pier. The promotion runs detached, so the agent can stop itself as the new core takes over.