Skip to main content

Configuration reference

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

VariableDefaultRequiredSecretDescription
APP_ENVdevelopmentNoNoDeployment label; informational only.
LOG_LEVELinfoNoNoLog verbosity: debug / info / warn / error.

API

VariableDefaultRequiredSecretDescription
API_ADDR127.0.0.1:8080NoNoAddress the API listens on; set 0.0.0.0:8080 in a container.
API_SHUTDOWN_TIMEOUT10sNoNoGraceful shutdown deadline for in-flight HTTP requests.
OPENAPI_PATHapi/openapi/openapi.yamlNoNoFilesystem 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 originNoComma-separated browser origins allowed to call the API.
METRICS_ADDR0.0.0.0:9090NoNoOps 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

VariableDefaultRequiredSecretDescription
AUTH_OIDC_ISSUER_URL(empty)YesNoYour identity provider's issuer URL; protected API routes return 503 until this and the audience are both set.
AUTH_OIDC_AUDIENCE(empty)YesNoThe OIDC client ID / audience Planeon validates tokens against.
AUTH_OIDC_GROUPS_CLAIMgroupsNoNoToken claim read for group membership; supports dot-paths for nested claims (for example realm_access.roles).
AUTH_OIDC_ROLES_CLAIMrolesNoNoToken claim read for role membership.
AUTH_BOOTSTRAP_ADMIN_EMAILS(empty)Recommended for first loginNoEmail address(es) granted the platform_admin role automatically on first sign-in.
AUTH_BOOTSTRAP_ADMIN_SUBJECTS(empty)NoNoSame bootstrap mechanism as above, matched on OIDC subject instead of email.
AUTH_BOOTSTRAP_OIDC_GROUP_BINDINGS(empty)NoNoComma-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).

VariableDefaultRequiredSecretDescription
NEXT_PUBLIC_API_BASE_URLhttp://localhost:8080Yes in productionNoPublic base URL of the API the browser calls; set to your API's external origin.
NEXT_PUBLIC_OIDC_AUTHORITY(empty)YesNoOIDC 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)YesNoOIDC client ID of the web console application.
NEXT_PUBLIC_OIDC_SCOPEopenid profile email groupsNoNoScopes requested at sign-in; include offline_access if you rely on silent token refresh.
NEXT_PUBLIC_OIDC_LOGOUT_URL(empty)NoNoExplicit end-session URL. Leave empty to use your provider's standards-compliant end_session_endpoint from OIDC discovery.

Database

VariableDefaultRequiredSecretDescription
DATABASE_URLpostgres://proxmox:proxmox@127.0.0.1:5432/proxmox_vdi_admin?sslmode=disableYesYesPostgreSQL connection string; every process fails to start if this is unset.
DATABASE_MAX_CONNS10NoNoMaximum 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.

VariableDefaultRequiredSecretDescription
POSTGRES_DBplaneonYes, for the bundled containerNoName of the database created on first start; must match the database in DATABASE_URL.
POSTGRES_USERplaneonYes, for the bundled containerNoSuperuser role created on first start; must match the user in DATABASE_URL.
POSTGRES_PASSWORD(empty)Yes, for the bundled containerYesPassword for POSTGRES_USER; must match the password in DATABASE_URL.

Redis

VariableDefaultRequiredSecretDescription
REDIS_ADDR127.0.0.1:6379YesNoRedis host:port; every process fails to start if this is unset.
REDIS_PASSWORD(empty)NoYesRedis auth password, if your Redis instance requires one.
REDIS_DB0NoNoRedis logical database index.

Secrets at rest

VariableDefaultRequiredSecretDescription
SECRETS_MASTER_KEY(empty)Yes for productionYesAES 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)NoYesThe retiring master key, set only for the duration of a key-rotation window.

Gateway & guacd

VariableDefaultRequiredSecretDescription
GATEWAY_ADDR0.0.0.0:8081NoNoThe gateway's own listen address.
GUACD_ADDRESSguacd:4822NoNohost:port of guacd.
GATEWAY_PUBLIC_WS_URL(empty)Yes for browser desktop accessNoPublic wss:// URL of the gateway tunnel, returned to the browser in the connection-token response.
GUACD_LOG_LEVELinfoNoNoLog 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

VariableDefaultRequiredSecretDescription
WORKER_POLL_INTERVAL1mNoNoJob queue polling interval.
POOL_RECONCILE_INTERVAL30sNoNoHow often pool reconciliation runs.
POOL_RECONCILE_BATCH_SIZE50NoNoMaximum pools reconciled per cycle.
GUEST_AGENT_WAIT_TIMEOUT10mNoNoHow long provisioning waits for the guest agent to respond before failing that step.
WINDOWS_READY_WAIT_TIMEOUT30mNoNoHow long provisioning waits for Windows Sysprep/OOBE to finish before failing that step.
WORKER_LEASE_DURATION5mNoNoHow long a leased job may run without a heartbeat before another worker reclaims it.
WORKER_SHUTDOWN_TIMEOUT30sNoNoGraceful 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_MONTHS0NoNoTrailing months of audit events kept; 0 keeps everything.
AUDIT_MAINTENANCE_INTERVAL24hNoNoHow often the worker provisions upcoming audit partitions and prunes expired ones.

Licensing

VariableDefaultRequiredSecretDescription
LICENSE_REPORT_URL(empty)NoNoVendor activation-report endpoint; empty disables activation reporting entirely (the Free edition never reports regardless).
LICENSE_REPORT_INTERVAL24hNoNoActivation-report cadence (jittered).
LICENSE_WATERMARK_INTERVAL1hNoNoHow often the worker persists the monotonic license-expiry watermark.
LICENSE_MANIFEST_PATH(empty → <executable>.manifest)NoNoPath to the signed build manifest used for tamper detection.

See Licensing for what these control.