Skip to main content

Configuration Reference

Every configuration option of the Plumber Platform backend is an environment variable, named PLUMBER_*.

Info

Credentials are not configured here. They are stored encrypted in the Platform database: the GitLab OAuth application is set once by plumber-bootstrap; the GitLab access token, SMTP and the licence are set in Settings as an Admin.

Caution

On Docker Compose installs, compose.yml already sets most of these from a handful of .env variables (DOMAIN_NAME, GITLAB_URL, the secrets, the profile). Variables the compose file pins directly, such as PLUMBER_BASE_URL, PLUMBER_OIDC_AUDIENCE, PLUMBER_LISTEN_* and PLUMBER_COOKIE_SECURE, are derived there: edit the compose file if you must override them. On Kubernetes, the chart maps platform.* values onto the same variables, and backend.extraEnv sets anything else.

Required configuration

VariableDefaultMeaning
PLUMBER_BASE_URLhttp://localhost:8080The public origin of this install, no trailing slash. It is what the browser, the OAuth redirect and the pipelines address
PLUMBER_TOKEN_ENCRYPTION_KEY(none)AES-256-GCM key sealing every stored GitLab secret and token: exactly 64 hex characters (openssl rand -hex 32). Cannot be rotated in place, back it up
PLUMBER_DB_HOSTlocalhostPostgreSQL host
PLUMBER_DB_PORT5432PostgreSQL port
PLUMBER_DB_USERplumberPostgreSQL user
PLUMBER_DB_PASSWORDplumberPostgreSQL password. Always set your own
PLUMBER_DB_NAMEplumberPostgreSQL database name
PLUMBER_REDIS_ADDRlocalhost:6379Redis address, host:port
PLUMBER_REDIS_URL(empty)Redis connection URL (redis:// or rediss://), an alternative to PLUMBER_REDIS_ADDR. Never set both
PLUMBER_OIDC_AUDIENCE(empty)The aud claim CI OIDC tokens must carry, byte-identical to what pipelines request. Empty rejects every push
PLUMBER_OIDC_ALLOWED_ISSUERS(empty: every push is rejected)Comma-separated GitLab base URLs allowed to push results. Docker Compose and the Helm chart set it to the GitLab URL for you (GITLAB_URL / platform.gitlabUrl)

Network

VariableDefaultMeaning
PLUMBER_LISTEN_ADDR0.0.0.0Address the backend listens on
PLUMBER_LISTEN_PORT8080Port the backend listens on
PLUMBER_COOKIE_SECUREfalseMark the session cookie Secure. Keep it true behind TLS
PLUMBER_TRUST_FORWARDED_FORfalseTrust X-Forwarded-For for per-IP rate limits. Keep it true behind a reverse proxy or an ingress
PLUMBER_TRUSTED_PROXY_CIDRS(empty)Extra trusted proxy CIDRs, beyond the private ranges already trusted
PLUMBER_BASE_URL_REJECT_PRIVATEfalseReject a base URL that resolves to a private address
PLUMBER_SPEC_PUBLICfalseServes /api/v1/openapi.yaml without authentication; development only, never enable in production

Database TLS and pooling

VariableDefaultMeaning
PLUMBER_DB_SSLMODEdisableOne of disable, allow, prefer, require, verify-ca, verify-full
PLUMBER_DB_SSLROOTCERT(empty)Path to the CA certificate. Unreadable means a fatal error at startup
PLUMBER_DB_SSLCERT(empty)Path to the client certificate. Unreadable means a fatal error at startup
PLUMBER_DB_SSLKEY(empty)Path to the client key. Unreadable means a fatal error at startup
PLUMBER_DB_TIMEZONEUTCTimezone for database operations
PLUMBER_DB_MAX_OPEN_CONNS25Maximum open connections in the pool
PLUMBER_DB_MAX_IDLE_CONNS5Maximum idle connections in the pool
PLUMBER_DB_CONN_MAX_LIFETIME1hMaximum lifetime of a pooled connection

Sessions and logs

VariableDefaultMeaning
PLUMBER_SESSION_TTL168hValidity of a user session
PLUMBER_ROLE_CACHE_TTL5mHow long a user’s resolved role is cached
PLUMBER_LOG_LEVELinfodebug, info, warn or error
PLUMBER_LOG_FORMATjsontext for human-readable logs; anything else is JSON

Trust

VariableDefaultMeaning
PLUMBER_PROVIDER_CA_BUNDLE(empty)Path to a PEM bundle trusted when calling GitLab
PLUMBER_REPORT_SMTP_CA_BUNDLE(empty)Path to a PEM bundle trusted when calling the SMTP server
PLUMBER_REPORT_SMTP_REJECT_PRIVATE_RELAYfalseRefuse an SMTP relay that resolves to a private address

Update check

VariableDefaultMeaning
PLUMBER_UPDATE_CHECK_URLhttps://raw.githubusercontent.com/getplumber/plumber-platform/main/latest.jsonManifest polled to tell you a newer release exists. Must be https://, or the literal off to disable it (air-gapped installs)
PLUMBER_UPDATE_CHECK_CRON0 6 * * *When to poll it (5-field cron, UTC)
PLUMBER_UPDATE_CHECK_TIMEOUT5sTimeout of the poll

Background work

All cron expressions are 5-field and evaluated in UTC.

VariableDefaultMeaning
PLUMBER_SYNC_CRON20 1 * * *Daily synchronisation of the project inventory from GitLab
PLUMBER_SYNC_TIMEOUT20mDeadline of a whole sync run
PLUMBER_SYNC_DETECT_TIMEOUT10sDeadline of the per-project detection step during a sync
PLUMBER_REDETECT_BATCH100Projects re-detected per sync run; 0 disables re-detection
PLUMBER_SYNC_MAX_VANISH_PERCENT30Safety brake: when one sync pass would flag more than this share of the known projects as gone from the provider (and more than PLUMBER_SYNC_MAX_VANISH_COUNT of them), the flagging is withheld and the run finishes with a warning; nothing is removed. 0 or less disables the brake
PLUMBER_SYNC_MAX_VANISH_COUNT10Absolute count the same pass must also exceed before the brake fires; at or below it the brake never fires
PLUMBER_SYNC_WORKERS8Parallel workers of the sync engine; clamped to half of PLUMBER_DB_MAX_OPEN_CONNS so sync never starves the API of database connections
PLUMBER_WATCHDOG_CRON*/15 * * * *Sweep for runs that never reported back
PLUMBER_RUNNING_TIMEOUT15mAfter this, a running analysis is considered interrupted
PLUMBER_SCORE_ROLLUP_CRON0 * * * *Hourly score rollup
PLUMBER_SNAPSHOT_TIMEOUT60sDeadline of a configuration snapshot
PLUMBER_RESOLVE_TIMEOUT10sDeadline of one resolved-control lookup
PLUMBER_RESOLVE_MAX_CONCURRENT2Concurrent resolved-control lookups
PLUMBER_RETRIGGER_TIMEOUT3mDeadline of a re-check (pipeline re-trigger)
PLUMBER_FIX_TIMEOUT60sDeadline of an automated fix
PLUMBER_ONBOARD_TIMEOUT60sDeadline of one project onboarding. Must stay below PLUMBER_SYNC_TIMEOUT
PLUMBER_INTERACTIVE_WORKERS4Workers serving user-triggered background jobs
PLUMBER_FANOUT_CRON*/2 * * * *Fan-out tick for queued work
PLUMBER_FANOUT_BATCH10Items dispatched per fan-out tick
PLUMBER_REPORT_SCHEDULE_TICK_CRON*/15 * * * *Tick that looks for scheduled reports to send
PLUMBER_REPORT_SCHEDULE_SEND_TIMEOUT60sDeadline of sending one scheduled report
PLUMBER_RETENTION_CRON0 4 * * 0Weekly retention sweep (Sunday 04:00 UTC)
PLUMBER_RETENTION_DAYS30How long analyses are kept. Values below 2 are rejected
PLUMBER_RETENTION_BATCH_SIZE500Rows deleted per retention batch
PLUMBER_RETENTION_BATCH_TIMEOUT10sDeadline of one retention batch
PLUMBER_RETENTION_BLOB_GRACE_PERIOD1hGrace period before an orphaned blob is deleted

Rate limits

Outbound, per provider call class:

VariableDefaultMeaning
PLUMBER_PROVIDER_LIMIT_WINDOW60sLength of the outbound rate-limit window
PLUMBER_PROVIDER_LIMIT_BACKGROUND900Provider calls per window for background work
PLUMBER_PROVIDER_LIMIT_INTERACTIVE300Provider calls per window for interactive work
PLUMBER_PROVIDER_LIMIT_USER300Provider calls per window and per user

Inbound:

VariableDefaultMeaning
PLUMBER_INBOUND_LIMIT_WINDOW60sLength of the inbound rate-limit window
PLUMBER_INBOUND_LIMIT_PUSH_PER_IP600Result pushes accepted per window and per IP
PLUMBER_INBOUND_LIMIT_LOGIN_PER_IP120Login attempts per window and per IP
PLUMBER_INBOUND_LIMIT_INVALIDATE_CACHE_PER_SESSION20Cache invalidations per window and per session
PLUMBER_SSE_MAX_PER_USER16Concurrent live-update streams per user; 0 disables the limit

Ingestion caps

The push body is untrusted input. These caps bound what one push may contain; a body that exceeds them is rejected.

VariableDefaultMeaning
PLUMBER_INGEST_MAX_POLICIES100Policies in one push
PLUMBER_INGEST_MAX_FINDINGS_PER_POLICY1000Findings for one policy
PLUMBER_INGEST_MAX_FINDINGS_AGGREGATE5000Findings in one push, all policies together
PLUMBER_INGEST_MAX_SCALAR_STRING_BYTES1024Length of any single string value
PLUMBER_INGEST_MAX_DATA_BYTES65536Size of a finding’s data object
PLUMBER_INGEST_MAX_EFFECTIVE_CONFIG_BYTES262144Size of the reported effective configuration
PLUMBER_INGEST_MAX_VARIABLE_VALUE_BYTES1024Length of a reported CI variable value
PLUMBER_INGEST_MAX_NESTING_DEPTH100Nesting depth of the JSON body
PLUMBER_INGEST_MAX_COLLECTION_MISSING_FIELDS50Reported missing-field entries kept per collection

Frontend

VariableDefaultMeaning
API_INTERNAL_URL(none)Where server-side rendering calls the backend. http://backend:8080/api on the Compose stack
GITLAB_URL(none)GitLab instance URL, used for deep links

There is no NEXT_PUBLIC_* variable: the browser always calls the API same-origin under /api.

Bootstrap only

Read by plumber-bootstrap, never by the running backend.

VariableDefaultMeaning
PLUMBER_BOOTSTRAP_CLIENT_SECRET(none)Secret of the GitLab OAuth application