Skip to content

v0.19.0 — relay on Postgres, direct serve mode

Choose a tag to compare

@github-actions github-actions released this 03 Sep 19:05
· 23 commits to main since this release
a1b4010

Promoted from v0.19.0-rc.1 as a same-commit re-tag: identical binaries, now validated in production — the hosted relay at public.getpiper.dev has been running this build on Postgres since 2026-09-03, with its data carried over by the copier (~2 s of downtime, every agent re-registered with its existing token).

The headline change is infrastructure: piper-relay stores its state in Postgres instead of a SQLite file.

Manual upgrade steps — read before upgrading

Relay operators (hosted or self-hosted)

  1. Provision Postgres and set PIPER_RELAY_DB_URL. The relay refuses to start without it (PIPER_RELAY_DB_URL is required (postgres://user:password@host/dbname)). Tables are created on first start. PIPER_RELAY_DATA_DIR remains the mount point for the TLS pair and the GitHub App key; relay.db is no longer read or written. Full procedure: docs/runbooks/relay-deploy.md → 2. Configure.
  2. Existing data: copy it with the one-off cmd/relay-sqlite-to-pg (go run ./cmd/relay-sqlite-to-pg -sqlite relay.db -pg "$PIPER_RELAY_DB_URL") before starting the new binary — tokens, accounts, GitHub App links, custom domains, and repo bindings survive; no re-enrollment. The copier is temporary and is removed after the hosted cutover (#516). Or start empty and let boxes re-login. Running relay and Postgres together on one public-IP host? The runbook's Single host with compose section is the exact procedure used for the hosted relay's cutover, including the host-networking, certbot-mount, and nightly-dump details.
  3. systemd: the shipped piper-relay.service now carries After=postgresql.service and StartLimitIntervalSec=0, so a relay that boots before its database keeps retrying instead of tripping systemd's start-rate limit. Install the new unit file, not just the binary.
  4. Relay before agents, as always. The agent↔relay wire protocol is unchanged, so boxes on v0.18.0 keep working against a v0.19.0 relay.

Agent (piperd) operators

domain_config gained a serve column (direct-serve mode, #508). Schema is applied with CREATE TABLE IF NOT EXISTS, so an existing piper.db does not pick it up on its own. Either apply it in place before restarting —

sqlite3 /var/lib/piper/piper.db "ALTER TABLE domain_config ADD COLUMN serve TEXT NOT NULL DEFAULT 'relay';"

— or start with a fresh DB and redeploy. Boxes without a custom domain configured are unaffected either way.

What's new

  • Relay on Postgres (#515, #517): one shared database for every relay process; SQLite removed from the relay. SQLite's global write lock is replaced by row-level locking on the enroll/app/domain cap checks and on the parked-webhook drain, each covered by a concurrency test against real Postgres. Foreign keys are now enforced. Fixes a latent tie-break in org-target GitHub App install routing that would have picked the wrong org under Postgres NULL ordering.
  • Direct serve mode (#505/#508, #506/#511): a box-wide custom domain can be served by the box's own :443 (DNS → box), with the relay kept for login, webhooks, and control; per-app custom domains get DNS-01 certs through the same token source, no relay splice.
  • Direct HTTPS on a never-enrolled box (#509).
  • PROXY protocol v2 on the relay's public listeners, opt-in via PIPER_RELAY_PROXY_PROTOCOL=1 (#485/#500), so rate limiting and logs key on the real client IP behind a trusted L4 proxy.
  • TUI: list and switch to relay boxes (#504).
  • Relay logs failed terminate-path TLS handshakes, rate-gated (#501). Token and installation listings order by insertion, not lexical RFC3339Nano (#503). Tilde-free asset names for prerelease debs (#502). Repo hygiene: issue forms, PR template, SECURITY.md, CONTRIBUTING.md (#512, #514).

Still one replica

Postgres removes the database as a reason the relay can't scale out, but two per-process states remain — tunnel sessions and in-flight login flows — so run exactly one relay until those follow-ups land. The runbook's container section spells this out.

Known issues shipped open

  • PIPER_RELAY_DATA_DIR is created but no longer read by the relay itself (certs and the App key are addressed by their own env vars); it stays as the documented mount point for now.
  • cmd/relay-sqlite-to-pg ships in this release and will be deleted once the hosted relay has moved (#516).