piperdocs

# Environment variables

Every PIPER_* variable each binary reads, with its default and what it does. test/docs fails when a binary reads a name this page does not list.

Unset means the default applies. Booleans are enabled by the exact value 1 unless a row says otherwise.

## piperd

Read by internal/config and cmd/piperd. The systemd unit sets PIPER_DATA_DIR to /var/lib/piper and reads the rest from /etc/piper/piperd.env; packaging/systemd/piperd.env.example is the curated subset most installs touch. Values marked relay.json also come from the enrollment file piper login writes; the variable, when set, overrides it and marks the box operator-managed, so piper login refuses to enroll it.

NameDefaultMeaning
PIPER_DATA_DIR~/.piper/piperd (/var/lib/piper under systemd)Directory for the SQLite database, relay.json, and certificates.
PIPER_API_ADDR127.0.0.1:8088Control API listen address. A loopback bind serves without a token; any other bind requires a bearer token (see Control API). 0.0.0.0:8088 opens it to the LAN.
PIPER_WEBHOOK_ADDR127.0.0.1:8089Loopback listener for GitHub webhooks arriving through the relay.
PIPER_BASE_DOMAINpiper.localhost, or the enrolled relay's (relay.json)Apps are served at <name>.<base>. Setting it makes the box-wide domain env-managed: PUT/DELETE /v1/domain answer 409.
PIPER_CADDY_ADMINhttp://127.0.0.1:2019Admin API of the Caddy piperd manages.
PIPER_HTTP_ADDR:80Caddy's HTTP listen address.
PIPER_HTTPS_ADDR:443Caddy's HTTPS listen address.
PIPER_RELAY_ADDRunset (relay.json)Relay tunnel endpoint, host:port. Unset and no relay.json: the box is LAN-only.
PIPER_RELAY_TOKENunset (relay.json)Enrollment token presented to the relay.
PIPER_RELAY_TERMINATEDunset (relay.json)1: the relay terminates TLS for the shared domain; the box serves :80 and holds no certificate.
PIPER_WEBHOOK_SECRETunset (relay.json)HMAC key the relay signs brokered GitHub deliveries with.
PIPER_GITHUB_BROKEREDunset (relay.json)1: the relay holds the GitHub App, so this box needs no App credentials of its own.
PIPER_GITHUB_API_BASEhttps://api.github.comGitHub API base URL override, for tests against a fake GitHub.
PIPER_ACME_EMAILunsetACME account email for public certificates.
PIPER_ACME_CALet's Encrypt productionACME directory URL; set the staging URL while testing.
PIPER_DNS_PROVIDERunsetDNS-01 provider name for lego, for example cloudflare.
PIPER_TLS_CERT_FILEunsetStatic certificate path; with the key, skips ACME (tests, bring-your-own cert).
PIPER_TLS_KEY_FILEunsetStatic key path, paired with PIPER_TLS_CERT_FILE.
PIPER_PUBLIC_IPlearned from the relayPublic IP the direct-serve DNS guidance names; needed on a never-enrolled box or behind split-horizon NAT. Ignored with a log line when not an IP.
PIPER_SERVErelaydirect serves PIPER_BASE_DOMAIN from this box's own :443 instead of through the relay; see Direct serve. Any other value is ignored with a log line.
PIPER_SKIP_CADDYunsetTest only. Any value: do not start or manage a Caddy, because one is already running (the e2e suite).
PIPER_TEST_ISSUERunsetTest only. selfsigned replaces ACME with a self-signed issuer so the e2e suite can serve TLS without real DNS. Never set it on a real box.

## piper-relay

Read by cmd/piper-relay. See Run your own relay for a working configuration.

NameDefaultMeaning
PIPER_RELAY_DB_URLrequiredPostgres DSN, postgres://user:password@host/dbname. The relay creates its tables on first start.
PIPER_RELAY_APEXpublic.getpiper.devThe shared domain boxes get subdomains of.
PIPER_RELAY_TLS_ADDR:443Public TLS listener (SNI passthrough and shared-domain termination).
PIPER_RELAY_HTTP_ADDR:80Public HTTP listener.
PIPER_RELAY_TUNNEL_ADDR:7000Listener agents dial for their tunnels.
PIPER_RELAY_API_ADDR:8080Account and control API listener (api.<apex>).
PIPER_RELAY_TUNNEL_PUBLICunsetTunnel endpoint handed to boxes at enrollment (tunnel_endpoint in the enroll response), for when the dialable address differs from the bind.
PIPER_RELAY_ADVERTISE_HOSTfirst non-loopback IPv4Host this instance registers in the pool for the edge and other relays to reach it.
PIPER_RELAY_ZONEunsetFailure zone label; an agent's two tunnel sessions prefer relays in different zones.
PIPER_RELAY_MAX_AGENTS3Boxes per account.
PIPER_RELAY_MAX_APPS10Shared-domain app hostnames per account.
PIPER_RELAY_MAX_DOMAINS5Custom domains per account.
PIPER_RELAY_TLS_CERTunsetWildcard certificate for shared-domain termination; unset with the key means passthrough only. Re-read when the file changes.
PIPER_RELAY_TLS_KEYunsetKey paired with PIPER_RELAY_TLS_CERT.
PIPER_RELAY_PROXY_PROTOCOLunset1: :443, :80, and :7000 require a PROXY protocol v2 header. Set only when a trusted L4 proxy or piper-edge is the sole path to those ports.
PIPER_RELAY_GITHUB_CLIENT_IDunsetGitHub OAuth client ID for self-service piper login. Unset disables self-service login; boxes can only be operator-enrolled.
PIPER_RELAY_GITHUB_CLIENT_SECRETunsetClient secret paired with the ID; also required for browser login.
PIPER_RELAY_WEB_REDIRECTSunsetComma-separated https://host/path-prefix allowlist of browser-login redirect URIs (the dashboard). Empty disables browser login.
PIPER_RELAY_GITHUB_APP_IDunsetRelay-held GitHub App ID; with the key, the relay brokers webhooks and tokens for every box.
PIPER_RELAY_GITHUB_APP_KEYunsetPath to that App's private key PEM.
PIPER_RELAY_GITHUB_APP_SLUGunsetThat App's slug, so boxes can deep-link its install page.
PIPER_RELAY_GITHUB_WEBHOOK_SECRETunsetThat App's webhook secret.
PIPER_RELAY_OPS_ADDR127.0.0.1:9090Ops listener bind; binds when set or when either toggle below is on. Serves /readyz and /livez whenever bound.
PIPER_RELAY_METRICSunset1: serve Prometheus metrics on the ops listener.
PIPER_RELAY_LOGSunset1: serve the recent-log ring on the ops listener.
PIPER_RELAY_FAKE_APPROVEunsetTest only. 1 auto-approves device login when no GitHub client ID is set. Never set it on a public relay.

## piper-edge

Read by cmd/piper-edge. The edge shares the relays' database and fronts their public ports.

NameDefaultMeaning
PIPER_EDGE_APEXrequiredThe relays' apex, for example public.getpiper.dev.
PIPER_EDGE_DB_URLrequiredThe relays' Postgres DSN.
PIPER_EDGE_TLS_ADDR:443Public TLS listener.
PIPER_EDGE_HTTP_ADDR:80Public HTTP listener.
PIPER_EDGE_TUNNEL_ADDR:7000Tunnel listener agents dial.
PIPER_EDGE_PROXY_PROTOCOLunset1: the three public listeners require a PROXY protocol v2 header from a trusted balancer in front.
PIPER_EDGE_OPS_ADDR127.0.0.1:9090Ops listener bind, same rules as the relay's.
PIPER_EDGE_METRICSunset1: serve metrics on the ops listener.
PIPER_EDGE_LOGSunset1: serve the recent-log ring on the ops listener.

## piper CLI

Read by cmd/piper and the TUI. The CLI also reads PIPER_API_ADDR, PIPER_HTTP_ADDR, PIPER_HTTPS_ADDR, and PIPER_DATA_DIR from the running daemon's environment for piper agent status; those are piperd's variables, listed above.

NameDefaultMeaning
PIPER_ADDRthe saved box's address, else http://127.0.0.1:8088piperd control API to talk to; overrides the saved box.
PIPER_TOKENthe saved box's tokenBearer token for that API; overrides the saved box.
PIPER_REMOTEunsetDefault for --remote: base domain of a relay-connected box to drive through the relay.
PIPER_NO_BROWSERunset1: never open a browser (piper login --web, piper github setup, the TUI); print the URL instead.