Environment Variables
Primary configuration is via environment variables (set by Docker Compose). An optional config.yaml file can be mounted at /etc/planekeeper/config.yaml for complex nested configuration such as agent credentials (SSH keys, HTTPS PATs). Environment variables always override config file values.
Database
| Variable | Description | Default |
|---|---|---|
PG_HOST | PostgreSQL host | localhost |
PG_PORT | PostgreSQL port | 5432 |
PG_USER | PostgreSQL user | - |
PG_PASSWORD | PostgreSQL password | - |
PG_DBNAME | PostgreSQL database name | - |
PG_SSLMODE | PostgreSQL SSL mode | prefer |
Note: The Go connection string automatically appends
&timezone=UTCto enforce UTC on every database session. There is no separate timezone environment variable — UTC is enforced at three layers: PostgreSQL server config (Docker Composecommand), database-level default (ALTER DATABASE), and the connection string parameter.
Server
| Variable | Description | Default |
|---|---|---|
SERVER_ADDRESS | API server bind address | 0.0.0.0:3000 |
Agent
| Variable | Description | Default |
|---|---|---|
AGENT_SERVER_URL | Server URL for agent | - |
AGENT_API_KEY | API key for agent authentication (serveragent auto-provisions from DB if empty) | - |
AGENT_POLL_INTERVAL | Agent poll interval (seconds) | 30 |
GITHUB_TOKEN | GitHub token for higher rate limits | - |
UI
| Variable | Description | Default |
|---|---|---|
CLIENT_UI_API_BASE_URL | Client UI API base URL | - |
INTERNAL_UI_API_BASE_URL | Internal UI API base URL | - |
Rate Limiting
| Variable | Description | Default |
|---|---|---|
RATE_LIMIT_MAX_REQUESTS | Max requests per window | 100 |
RATE_LIMIT_WINDOW_SECONDS | Rate limit window (seconds) | 60 |
RATE_LIMIT_SKIP_FAILED | Skip failed requests in rate limit | false |
Notifications
| Variable | Description | Default |
|---|---|---|
NOTIFICATION_BATCH_SIZE | Deliveries per notifier poll | 100 |
NOTIFICATION_POLL_INTERVAL | Notifier poll frequency | 5s |
NOTIFICATION_MAX_RETRIES | Max retry attempts | 12 |
NOTIFICATION_ACK_TOKEN_EXPIRY | Ack token expiry duration | 24h |
NOTIFICATION_BASE_URL | Base URL for ack callbacks | - |
NOTIFICATION_ALLOW_PRIVATE_URLS | Allow RFC1918/localhost webhooks | false |
NOTIFICATION_RETRY_POLL_INTERVAL | How often the retry processor polls | 30s |
EOL Sync
| Variable | Description | Default |
|---|---|---|
EOLSYNC_REQUESTS_PER_SECOND | Rate limit for endoflife.date API | 2.0 |
EOLSYNC_MAX_RETRIES | Max retries per EOL product sync | 3 |
EOLSYNC_RETRY_BACKOFF_BASE | Base backoff seconds for EOL retries | 5 |
Gather Jobs
| Variable | Description | Default |
|---|---|---|
GATHER_FULL_SYNC_INTERVAL | How often to force a full re-fetch for incremental gather jobs (Go duration format) | 336h (2 weeks) |
Note: Incremental sync currently applies only to
github_releasesgather jobs. When a GitHub gather job has completed a full sync, subsequent runs only fetch releases newer than the latest known release date. Setting this interval to0disables incremental mode (every run is a full sync).
Early Access
| Variable | Description | Default |
|---|---|---|
EARLY_ACCESS_ENABLED | Enables waitlist mode on landing page | false |
Maintenance Mode
| Variable | Description | Default |
|---|---|---|
MAINTENANCE_MODE | When true, Client UI shows a maintenance page on all protected routes. The API health checker is skipped and the maintenance page is shown immediately. Use for planned downtime windows. | false |
Note:
MAINTENANCE_MODEonly affects the Client UI. The Internal UI is not affected — admins can still access the system during maintenance. For advance warnings (before the outage starts), use the maintenance announcement feature in the Internal UI instead.
Supabase Auth (Optional)
| Variable | Description | Default |
|---|---|---|
SUPABASE_URL | Supabase project URL (clientui + internalui) | - |
SUPABASE_PUBLISHABLE_KEY | Supabase publishable API key (clientui + internalui) | - |
SUPABASE_JWT_SECRET | JWT signing secret (server + clientui + internalui) | - |
SUPABASE_KEEPALIVE_EMAIL | Test account email for keepalive sign-ins (server only) | - |
SUPABASE_KEEPALIVE_PASSWORD | Test account password for keepalive sign-ins (server only) | - |
AUTH_CALLBACK_URL | OAuth callback URL (clientui only) | - |
AUTH_COOKIE_SECURE | Set Secure flag on auth cookies | true |
Note: When Supabase is configured for the Internal UI, only email/password login is supported (no OAuth, no signup). Access is gated to users in the
global_adminstable. The Internal UI also requiresPG_*database variables for admin lookups.Keepalive: When
SUPABASE_KEEPALIVE_EMAILandSUPABASE_KEEPALIVE_PASSWORDare set, the server runs a background service that periodically signs in to Supabase during business hours (14:00–22:00 UTC) to prevent free-tier project pausing. The credentials should belong to a dedicated test account.
Infrastructure / Docker Compose
These variables are used in go/planekeeper/docker/docker-compose.yml and .env.prod.example for deployment configuration:
| Variable | Description | Default |
|---|---|---|
DOMAIN | Public domain name for Traefik routing (e.g., www.planekeeper.com) | - |
INTERNAL_DOMAIN | Internal admin domain for Traefik routing (e.g., admin.planekeeper.com) | - |
ACME_EMAIL | Let’s Encrypt certificate notification email | - |
CF_DNS_API_TOKEN | Cloudflare API token for DNS-01 challenge | - |
CF_API_EMAIL | Cloudflare global API email (legacy auth) | - |
CF_API_KEY | Cloudflare global API key (legacy auth) | - |
VERSION | Docker image tag | latest |
API_REPLICAS | Number of API server replicas | 2 |
CLIENTUI_REPLICAS | Number of client UI replicas | 1 |
SERVERAGENT_REPLICAS | Number of server agent replicas | 1 |
NOTIFIER_REPLICAS | Number of notifier replicas | 1 |
Important Notes
Note: Agents derive their
organization_idfrom the API key via the heartbeat endpoint. All services derive org context from their authentication mechanism rather than a global env var.
Note: The serveragent auto-provisions its API key from the database when
AGENT_API_KEYis not set butPG_*database variables are configured. Each replica gets a unique key namedserveragent-auto-<hostname>with a 30-day TTL. Keys are deactivated on graceful shutdown.
Note: When Supabase variables are not set, ClientUI uses legacy API key login. When set, ClientUI also needs
PG_*database variables for user/membership lookups.
Warning: In
go/planekeeper/docker/docker-compose.yml, the host-side.envvariableSERVERAGENT_API_KEYis mapped to the container’sAGENT_API_KEYenvironment variable. This indirection means operators setSERVERAGENT_API_KEYin their.envfile, but application code readsAGENT_API_KEY.