Planeon's backend services (api, worker, gateway) are configured entirely
through environment variables, all read from a single Config struct at
startup. The Docker Compose,
VM/systemd, and
Kubernetes/Helm
install guides show these assembled into a working planeon.env /
values.yaml — start there for a first install. Use this page when you
need the complete picture of what each variable does.
This page is exhaustive: it covers every variable the api, worker, gateway, and web services read, plus the variables of the bundled PostgreSQL and guacd containers used by the Docker Compose guide. Your Proxmox VE cluster is not configured here — you connect it from the web console after first login.
General
| Variable | Default | Required | Secret | Description |
|---|
APP_ENV | development | No | No | Deployment label; informational only. |
LOG_LEVEL | info | No | No | Log verbosity: debug / info / warn / error. |
API
| Variable | Default | Required | Secret | Description |
|---|
API_ADDR | 127.0.0.1:8080 | No | No | Address the API listens on; set 0.0.0.0:8080 in a container. |
API_SHUTDOWN_TIMEOUT | 10s | No | No | Graceful shutdown deadline for in-flight HTTP requests. |
OPENAPI_PATH | api/openapi/openapi.yaml | No | No | Filesystem path to the OpenAPI document served at GET /openapi.yaml. The shipped container images override this default with a baked-in path (the Compose guide sets /usr/local/share/proxmox-vdi-admin/openapi.yaml) — leave as-is. |
API_CORS_ALLOWED_ORIGINS | (empty) | Yes, if the web console is served from a different origin | No | Comma-separated browser origins allowed to call the API. |
METRICS_ADDR | 0.0.0.0:9090 | No | No | Ops listener for GET /metrics, /healthz, /readyz; set to an explicit empty value to disable. Shared setting shape for the api and worker processes — see Observability. |
OIDC / authentication
| Variable | Default | Required | Secret | Description |
|---|
AUTH_OIDC_ISSUER_URL | (empty) | Yes | No | Your identity provider's issuer URL; protected API routes return 503 until this and the audience are both set. |
AUTH_OIDC_AUDIENCE | (empty) | Yes | No | The OIDC client ID / audience Planeon validates tokens against. |
AUTH_OIDC_GROUPS_CLAIM | groups | No | No | Token claim read for group membership; supports dot-paths for nested claims (for example realm_access.roles). |
AUTH_OIDC_ROLES_CLAIM | roles | No | No | Token claim read for role membership. |
AUTH_BOOTSTRAP_ADMIN_EMAILS | (empty) | Recommended for first login | No | Email address(es) granted the platform_admin role automatically on first sign-in. |
AUTH_BOOTSTRAP_ADMIN_SUBJECTS | (empty) | No | No | Same bootstrap mechanism as above, matched on OIDC subject instead of email. |
AUTH_BOOTSTRAP_OIDC_GROUP_BINDINGS | (empty) | No | No | Comma-separated <claim value>=<local group key> bootstrap OIDC group bindings. |
Web console (browser)
These NEXT_PUBLIC_* values configure the web console's browser-side OIDC
client and its API endpoint. They are read by the web service; in the
released planeon/web image they are supplied at container start (if your
console ignores a change, check the release notes for how that image consumes
them).
| Variable | Default | Required | Secret | Description |
|---|
NEXT_PUBLIC_API_BASE_URL | http://localhost:8080 | Yes in production | No | Public base URL of the API the browser calls; set to your API's external origin. |
NEXT_PUBLIC_OIDC_AUTHORITY | (empty) | Yes | No | OIDC issuer/authority URL the browser uses; together with the client ID it gates whether the console's sign-in is configured. Must match the api's AUTH_OIDC_ISSUER_URL. |
NEXT_PUBLIC_OIDC_CLIENT_ID | (empty) | Yes | No | OIDC client ID of the web console application. |
NEXT_PUBLIC_OIDC_SCOPE | openid profile email groups | No | No | Scopes requested at sign-in; include offline_access if you rely on silent token refresh. |
NEXT_PUBLIC_OIDC_LOGOUT_URL | (empty) | No | No | Explicit end-session URL. Leave empty to use your provider's standards-compliant end_session_endpoint from OIDC discovery. |
Database
| Variable | Default | Required | Secret | Description |
|---|
DATABASE_URL | postgres://proxmox:proxmox@127.0.0.1:5432/proxmox_vdi_admin?sslmode=disable | Yes | Yes | PostgreSQL connection string; every process fails to start if this is unset. |
DATABASE_MAX_CONNS | 10 | No | No | Maximum pgx connection pool size, per process. |
Bundled PostgreSQL container
When you run the bundled postgres container (as in the Docker Compose guide),
these configure its initial database and superuser. They are read by the
postgres image, not by Planeon — keep them in sync with the credentials in
DATABASE_URL. With an external managed PostgreSQL you don't set these.
| Variable | Default | Required | Secret | Description |
|---|
POSTGRES_DB | planeon | Yes, for the bundled container | No | Name of the database created on first start; must match the database in DATABASE_URL. |
POSTGRES_USER | planeon | Yes, for the bundled container | No | Superuser role created on first start; must match the user in DATABASE_URL. |
POSTGRES_PASSWORD | (empty) | Yes, for the bundled container | Yes | Password for POSTGRES_USER; must match the password in DATABASE_URL. |
Redis
| Variable | Default | Required | Secret | Description |
|---|
REDIS_ADDR | 127.0.0.1:6379 | Yes | No | Redis host:port; every process fails to start if this is unset. |
REDIS_PASSWORD | (empty) | No | Yes | Redis auth password, if your Redis instance requires one. |
REDIS_DB | 0 | No | No | Redis logical database index. |
Secrets at rest
| Variable | Default | Required | Secret | Description |
|---|
SECRETS_MASTER_KEY | (empty) | Yes for production | Yes | AES envelope key encrypting stored credentials (Proxmox tokens, domain-join credentials, Guacamole connection tokens); the gateway refuses to start without it, and api/worker refuse to start once any encrypted data exists. |
SECRETS_MASTER_KEY_PREVIOUS | (empty) | No | Yes | The retiring master key, set only for the duration of a key-rotation window. |
Gateway & guacd
| Variable | Default | Required | Secret | Description |
|---|
GATEWAY_ADDR | 0.0.0.0:8081 | No | No | The gateway's own listen address. |
GUACD_ADDRESS | guacd:4822 | No | No | host:port of guacd. |
GATEWAY_PUBLIC_WS_URL | (empty) | Yes for browser desktop access | No | Public wss:// URL of the gateway tunnel, returned to the browser in the connection-token response. |
GUACD_LOG_LEVEL | info | No | No | Log verbosity of the bundled guacd container: trace, debug, info, warning, or error. This is guacd's own daemon setting, distinct from the backend LOG_LEVEL. In Docker Compose it is a Compose interpolation variable — set it in your shell environment or a .env file next to compose.yaml, not in planeon.env. |
Worker and reconciliation
| Variable | Default | Required | Secret | Description |
|---|
WORKER_POLL_INTERVAL | 1m | No | No | Job queue polling interval. |
POOL_RECONCILE_INTERVAL | 30s | No | No | How often pool reconciliation runs. |
POOL_RECONCILE_BATCH_SIZE | 50 | No | No | Maximum pools reconciled per cycle. |
GUEST_AGENT_WAIT_TIMEOUT | 10m | No | No | How long provisioning waits for the guest agent to respond before failing that step. |
WINDOWS_READY_WAIT_TIMEOUT | 30m | No | No | How long provisioning waits for Windows Sysprep/OOBE to finish before failing that step. |
WORKER_LEASE_DURATION | 5m | No | No | How long a leased job may run without a heartbeat before another worker reclaims it. |
WORKER_SHUTDOWN_TIMEOUT | 30s | No | No | Graceful drain deadline for an in-flight job on shutdown; exceed this in your process supervisor's own stop timeout (stop_grace_period in Compose, TimeoutStopSec in systemd). |
AUDIT_RETENTION_MONTHS | 0 | No | No | Trailing months of audit events kept; 0 keeps everything. |
AUDIT_MAINTENANCE_INTERVAL | 24h | No | No | How often the worker provisions upcoming audit partitions and prunes expired ones. |
Licensing
| Variable | Default | Required | Secret | Description |
|---|
LICENSE_REPORT_URL | (empty) | No | No | Vendor activation-report endpoint; empty disables activation reporting entirely (the Free edition never reports regardless). |
LICENSE_REPORT_INTERVAL | 24h | No | No | Activation-report cadence (jittered). |
LICENSE_WATERMARK_INTERVAL | 1h | No | No | How often the worker persists the monotonic license-expiry watermark. |
LICENSE_MANIFEST_PATH | (empty → <executable>.manifest) | No | No | Path to the signed build manifest used for tamper detection. |
See Licensing for what these control.