Skip to content

piper v0.20.0

Choose a tag to compare

@github-actions github-actions released this 04 Sep 18:09
· 19 commits to main since this release
91c8b3f

piper-edge: scale the relay out behind one address

piper-relay can now run as N processes behind a single public address. A new binary, piper-edge (ghcr.io/piperbox/piper-edge), is a stateless L4 entrypoint that routes every connection to the relay that owns the agent's tunnel (#521, epic #524).

What's new

  • piper-edge — peeks SNI on :443 and Host on :80, resolves the owning relay from an in-memory copy of the pool, and splices bytes to it with a PROXY v2 header so the relay still sees the real client IP. :7000 goes to the least-loaded relay; api.<apex> pins to the earliest-started relay (until #522). A relay whose dial fails is evicted (one retry on :7000 only). If Postgres is unreachable the edge keeps serving from memory.
  • Relay pool membership — each piper-relay heartbeats into relay_instances (5s; live for 15s) with the addresses it advertises (PIPER_RELAY_ADVERTISE_HOST, default first non-loopback IPv4) and leaves the pool on SIGTERM.
  • Tunnel ownership — agent_owners records which relay terminates which agent. Register upserts, unregister clears only its own row and only when no newer session is held, and every heartbeat re-asserts ownership for held agents with no live owner.
  • Cluster-aware control API — a piper command that lands on a relay not holding the agent is forwarded unchanged to the owner over :8080 (one hop, never two). GET /agents and the delete guard count live owners on any relay and fail closed on a lookup error.
  • NOTIFY-woken webhooks — parked GitHub events wake the owning relay through piper_events instead of waiting for the sweep.
  • Runbook: new Scale out section in docs/runbooks/relay-deploy.md with a compose example (edge on the host network, relays on the bridge with PIPER_RELAY_PROXY_PROTOCOL=1).

Upgrading

  • Relay schema: two new tables (relay_instances, agent_owners) created by CREATE TABLE IF NOT EXISTS on start. Nothing existing changes; no re-enroll, no data migration. Agents and the wire protocol are untouched, so relay-before-agents ordering does not apply — old agents and this relay interoperate both ways.
  • Single relay, no edge: everything works as before. Two behaviour changes: SIGTERM now always drains (leaves the pool, ≤5s), and a host with no non-loopback IPv4 must set PIPER_RELAY_ADVERTISE_HOST or the relay refuses to start.
  • Behind an edge: set PIPER_RELAY_PROXY_PROTOCOL=1 on every relay, PIPER_RELAY_ADVERTISE_HOST to an address the edge can dial, and give the edge PIPER_EDGE_DB_URL + PIPER_EDGE_APEX. Postgres must be reachable from the edge.

Known limits

  • api.<apex> (device flow, web login, rate limiter) is pinned to one relay until login-flow state moves to Postgres (#522).
  • A relay restart still drops its tunnels; agents redial from 1s backoff. Graceful drain is #523.