Environment variables
This page lists the operator-facing APP_* environment variables that are not already explained on a feature page. Each row was checked against the code that reads it, and each default is the fallback in that code. Variables that a feature page already documents (for example the APP_INGRESS_* hardening limits in Domains and ingress or the APP_PIPELINE_* settings in Pipelines) stay on those pages. Branding variables (APP_BRAND_*) are covered in White-labeling.
How to set these
Every variable on this page is read by a process at startup, so a change takes effect after a restart.
Installed with
install.sh: the control plane runs as thelevelrailsystemd service. The unit file sets onlyAPP_DATA_DIR,APP_HTTP_ADDR,APP_INGRESS_HTTP_ADDRandAPP_INGRESS_HTTPS_ADDRitself, with plainEnvironment=lines and noEnvironmentFile=. Add your own with a drop-in, which survives upgrades:bashsudo systemctl edit levelrailThen add the variables under a
[Service]heading and restart:ini[Service] Environment=APP_UPDATE_CHECK_INTERVAL=6h Environment=APP_SLOW_REQUEST_THRESHOLD=1sbashsudo systemctl restart levelrailThis is the same method Installing uses for
APP_ALLOW_INSECURE_LOGIN.Docker or Compose: pass them with
-e NAME=valueor anenvironment:block, as in the examples in Docker.Node agent: variables marked "agent" below are read by
levelrail-agent. Set them on the agent's container or service, not on the control plane. See Docker and Node provisioning.Command line client: variables marked "CLI" are read by
levelrail-cliin the shell where you run it.
Duration values use Go duration syntax such as 30s, 5m, 1h30m. Most variables fall back to their default when the value is unset or invalid; the exceptions are called out in the tables.
Builds and build cache
The control plane builds images with BuildKit. By default each build starts from whatever cache BuildKit already holds. These variables add a shared cache. See Build node routing for dedicated build nodes.
| Variable | Default | Meaning |
|---|---|---|
APP_BUILD_CACHE_DIR | unset (no local cache backend) | Directory for BuildKit's local cache backend. Builds import from and export to it. Control plane. |
APP_BUILD_CACHE_REGISTRY | unset | Image reference of a registry cache (for example registry.example.com/cache) shared across build nodes. When set, it takes priority over the registry settings saved in the dashboard. Control plane. |
APP_BUILD_CACHE_REGISTRY_INSECURE | unset (off) | Set to exactly true to allow a plain-HTTP or self-signed cache registry. Only applies when APP_BUILD_CACHE_REGISTRY is set. Control plane. |
Git webhook (single repository mode)
These variables turn on the control plane's own POST /webhook receiver for one repository. They are separate from the per-app webhooks and GitHub App flow in Git integrations. The three required variables must all be set. If any is missing, the control plane still starts and logs a webhook not configured warning, and only this receiver is unavailable.
| Variable | Default | Meaning |
|---|---|---|
APP_GIT_REPO_URL | none, required | Git remote the receiver clones when a push arrives. Control plane. |
APP_WEBHOOK_SECRET | none, required | Shared secret used to verify the X-Hub-Signature-256 header on incoming pushes. Control plane. |
APP_IMAGE_REPO | none, required | Image repository that built images are tagged into. Control plane. |
APP_GIT_BRANCH | main | Only pushes to this branch trigger a deploy. Control plane. |
APP_SPEC_DIR | . (the process working directory) | Directory searched for the app spec file. See App spec reference. Control plane. |
APP_SERVICE_NAME | the only service in the spec | Which service from the spec to deploy. Required when the spec declares more than one service. Control plane. |
GitHub App manifest
| Variable | Default | Meaning |
|---|---|---|
APP_GITHUB_APP_MANIFEST_FILE | ./github-app-manifest.yaml | YAML file with default_permissions (a map) and default_events (a list) that a newly registered GitHub App requests. A missing file means the built-in set: contents:read, metadata:read, repository_hooks:write, statuses:write, deployments:write, and no events. A file that exists but cannot be parsed stops the load with an error. The relative default resolves against the process working directory, which is the data directory under the installer's unit. Control plane. |
Pipelines and OIDC
The pipeline engine's own tuning variables are listed in Pipelines. These extra ones cover the scheduler, commit status reporting, and the OIDC token service described in Pipelines OIDC. Non-positive or unparseable values for the duration variables here fall back to the default without a warning.
| Variable | Default | Meaning |
|---|---|---|
APP_PIPELINE_SCHEDULER_INTERVAL | 30s | How often the pipeline scheduler runs. Control plane. |
APP_GIT_STATUS_TIMEOUT | 10s | Time limit for each commit status post a pipeline run sends to the git forge. Control plane. |
APP_OIDC_KEY_RETIRE_GRACE | 24h | How long a rotated-out signing key stays published in the JWKS document before it is removed. Control plane. |
APP_OIDC_JWKS_RATE_LIMIT_PER_MINUTE | 60 | Rate limit on the unauthenticated JWKS endpoint. Positive integer. Control plane. |
APP_OIDC_TOKEN_REQUEST_PORT | 9095 | Port of the runtime token request endpoint, bound to the Docker bridge gateway address so only job containers can reach it. Positive integer. Control plane. |
Scheduling and background intervals
Each of these is how often a background loop wakes to check for work. Standard five-field cron has one-minute granularity, so the one-minute defaults are the shortest useful value for the two cron-driven schedulers.
| Variable | Default | Meaning |
|---|---|---|
APP_BACKUP_SCHEDULER_INTERVAL | 1m | How often the database backup scheduler checks for backups whose cron schedule is due. See Backups and storage. Control plane. |
APP_SCHEDULED_TASK_SCHEDULER_INTERVAL | 1m | How often the scheduler checks for scheduled tasks that are due. Control plane. |
APP_DEPLOY_APPROVAL_SWEEP_INTERVAL | 5m | How often pending deploy approvals are checked against their 24 hour expiry. See Chat deploy approvals. Control plane. |
APP_RESOURCE_RECOMMENDATION_LOOKBACK | 168h (7 days) | History window used when computing app resource recommendations. Control plane. |
For the invalid-value behavior of the first three, see the note at the end of this page.
Control plane off-box backups
These tune the scheduled off-box copy of the control plane's own state and its restore drills, described in Control plane backup and Disaster recovery. Values that are unset, unparseable, or not greater than zero use the default. Control plane.
| Variable | Default | Meaning |
|---|---|---|
APP_CONTROL_PLANE_OFFBOX_RETAIN_WEEKLY | 4 | Number of weekly backups kept. Positive integer. |
APP_CONTROL_PLANE_OFFBOX_RETAIN_MONTHLY | 6 | Number of monthly backups kept. Positive integer. |
Point-in-time restore
| Variable | Default | Meaning |
|---|---|---|
APP_PITR_WAL_SEGMENT_BYTES | 16777216 (16 MiB) | WAL segment size, in bytes, that the restore path assumes when it maps a base backup's start position to a segment. Set it only if the Postgres server was initialized with a non-default WAL segment size. Positive integer. Control plane. See Managing databases. |
Log archive
The archiver's other settings are on Log archive. These two bound how much one run does. Positive values only; anything else uses the default. Control plane.
| Variable | Default | Meaning |
|---|---|---|
APP_LOG_ARCHIVE_MAX_WINDOWS_PER_RUN | 24 | Maximum number of one-hour windows archived in a single scheduled run. Integer. |
APP_LOG_ARCHIVE_MAX_BACKFILL | 24h | How far back a run may reach when it catches up on missed windows. Duration. |
Ingress
The edge hardening limits are in Domains and ingress. These two are not listed there. Control plane.
| Variable | Default | Meaning |
|---|---|---|
APP_INGRESS_RETRY_INTERVAL | 250ms | Pause between retries when a proxied backend cannot be reached during the APP_INGRESS_RETRY_WINDOW. A negative or unparseable value is a startup error, not a silent fallback. |
APP_INGRESS_SOCKET_ACTIVATION | auto | Controls use of sockets inherited from systemd. auto uses them if present. true (also 1, on) makes missing inherited sockets a startup error. false (also 0, off) ignores them. See Surviving a control plane restart. |
Certificates and request thresholds
| Variable | Default | Meaning |
|---|---|---|
APP_CERT_EXPIRY_WARNING_WINDOW | 336h (14 days) | How close to expiry a certificate must be before it counts as expiring, for both the certificate expiry alert rules and the API. Control plane. |
APP_SLOW_REQUEST_THRESHOLD | 500ms | API requests slower than this are logged at Warn level. Control plane. |
APP_CRITICAL_REQUEST_THRESHOLD | 2s | API requests slower than this are logged at Error level. Control plane. |
For all three, a value that does not parse logs a warning and uses the default. For the two request thresholds, zero or a negative duration also means the default.
Doctor and diagnosis
These tune levelrail-cli doctor and the structured diagnosis of failed deploys. See Troubleshooting and Deploy failures.
| Variable | Default | Meaning |
|---|---|---|
APP_DOCTOR_DISK_WARNING_BYTES | 1073741824 (1 GiB) | Free disk space below which the disk_space check warns. Integer bytes. Control plane. |
APP_DOCTOR_MASTER_KEY_ROTATION_WARN_DAYS | 365 | Age of the master key, in whole days, after which doctor suggests rotating it. See Master key rotation. Control plane. |
APP_DOCTOR_NETWORK_TIMEOUT | 5s | Shared time limit for the network checks in the doctor endpoint. Control plane. |
APP_DOCTOR_PUBLIC_IP_ENDPOINT | https://api.ipify.org | URL that returns the caller's public IP as plain text, used by the public_ip doctor check and by deploy preflight. Control plane. |
APP_DIAGNOSE_PROBE_TIMEOUT | 4s | Time limit for each live probe (container state and container logs) when diagnosing an app. Zero or invalid values use the default. Control plane. |
APP_ATTENTION_DIAGNOSE_LIMIT | 10 | Maximum number of distinct apps levelrail-cli attention asks the control plane to diagnose when it marks items as fixable. Integer, 0 skips diagnosis. CLI. |
Updates
| Variable | Default | Meaning |
|---|---|---|
APP_UPDATE_CHECK_INTERVAL | 1h | How often the control plane checks the configured release channel for a newer version. Control plane. |
SSH node provisioning
| Variable | Default | Meaning |
|---|---|---|
APP_SSH_NODE_PROVISION_TIMEOUT | 10m | Time limit for installing the agent over SSH, and how long the control plane waits for the new node to enroll before reporting the provision as failed. Zero or invalid values use the default. Control plane. See Node provisioning. |
Mesh networking
| Variable | Default | Meaning |
|---|---|---|
APP_MESH_KEY_FILE | levelrail-agent-mesh.key in the same directory as the agent identity file | Path where the agent stores its WireGuard private key. Only used when APP_MESH_ENABLED=1. Agent. See Network topology. |
Behavior to know about
- Scheduler intervals are not range checked.
APP_BACKUP_SCHEDULER_INTERVAL,APP_SCHEDULED_TASK_SCHEDULER_INTERVAL,APP_UPDATE_CHECK_INTERVALandAPP_DEPLOY_APPROVAL_SWEEP_INTERVALuse any value that parses as a Go duration, including zero or a negative one. Only an unparseable value falls back to the default. Use a positive duration. - Ingress variables fail closed. Unlike most settings on this page, an invalid
APP_INGRESS_*hardening value is returned as an error at startup rather than ignored.