OrkStageOrkStage

Configuration reference

Every OrkStage environment variable with its type, default and effect, from core settings and OIDC to the OpenTofu runner, email, secrets and licensing.

The API and the worker read the same typed configuration (packages/runtime/src/config.ts). They refuse to start on invalid values and list every problem they find. In local development they load a .env file from the repository root (cp .env.example .env). Real environments inject the variables.

Booleans accept true, false, 1 or 0.

Core

VariableTypeDefaultDescription
NODE_ENVdevelopment | test | productiondevelopmentproduction turns on Secure cookies and the production safety checks.
DATABASE_URLURLrequiredPostgres connection string, for example postgresql://platform:platform@localhost:5432/platform.
REDIS_URLURLrequiredRedis for queues and concurrency slots, for example redis://localhost:6379.
API_PORTinteger4000Port the API listens on.
API_PUBLIC_URLURLhttp://localhost:4000Public URL of the API.
WEB_PUBLIC_URLURLhttp://localhost:3000Public URL of the console. OIDC redirect URIs are built from it.
SESSION_SECRETstring, at least 32 charactersrequiredSigns the session cookie and the OIDC flow cookie. In production it must not start with change-me.
LOG_LEVELtrace, debug, info, warn, error or fatalinfoPino log level. Tokens, secrets, cookies and authorization headers are always redacted.
TRUST_PROXY_HOPSinteger, 0 to 51Reverse proxies in front of the API that add the client address to X-Forwarded-For. The console's /api proxy counts as one. The client address (rate limits, audit) is read that many hops back, so clients cannot set it. See rate limits behind proxies.
API_DOCS_ENABLEDbooleantrue, or false when NODE_ENV=productionServes the OpenAPI document and Swagger UI at /api/docs.

Authentication

VariableTypeDefaultDescription
AUTH_DEV_LOGIN_ENABLEDbooleanfalseEnables POST /auth/dev-login, which signs in with an email address only. Startup fails if it is true while NODE_ENV=production.
OIDC_<KEY>_ISSUERURLIssuer of an OIDC provider. <KEY> is any name in uppercase letters and digits.
OIDC_<KEY>_CLIENT_IDstringClient id registered at that provider.
OIDC_<KEY>_CLIENT_SECRETstringClient secret for that client id.
SESSION_IDLE_MINUTESinteger, 5 to 1440120A session unused for this long ends, even before its absolute limit of 12 hours.

Single sign on (OIDC)

A provider is enabled when all three OIDC_<KEY>_* variables are set and the issuer contains no <placeholder>. The keys ENTRA, GOOGLE and GITLAB get display names. Any other key is shown as written. Register this redirect URI at the provider:

<WEB_PUBLIC_URL>/api/v1/auth/oidc/<key>/callback      # key in lowercase, e.g. /oidc/entra/callback
Microsoft Entra ID
OIDC_ENTRA_ISSUER=https://login.microsoftonline.com/<tenant-id>/v2.0
OIDC_ENTRA_CLIENT_ID=<application id>
OIDC_ENTRA_CLIENT_SECRET=<client secret>

The flow uses the authorization code grant with PKCE (S256) and verifies state and nonce. The ID token's signature is checked against the keys the provider publishes (its JWKS), not only the TLS of the exchange. Accounts are linked only through an email address the provider has verified.

Microsoft Entra ID is the reference provider. Google and GitLab work through configuration alone but have had less testing.

GitHub sign in

GitHub has no OpenID Connect for people, so it has an OAuth 2 flow of its own with the same state and PKCE checks. Create an OAuth app (GitHub, Settings, Developer settings, OAuth Apps) with the callback <WEB_PUBLIC_URL>/api/v1/auth/oidc/github/callback, then:

OAUTH_GITHUB_CLIENT_ID=<client id>
OAUTH_GITHUB_CLIENT_SECRET=<client secret>
# GitHub Enterprise Server only:
OAUTH_GITHUB_URL=https://github.example.com

OrkStage asks for read:user and user:email, reads the person's id and emails once, and discards the access token. Only the primary, verified email can link to an account; the GitHub user id is the stable link afterwards, so a later email change at GitHub does not move the account.

Account linking

The same rules apply to every provider:

  1. A person who signed in with this provider before gets the same account (by the provider's id, never by email).
  2. Otherwise, a verified email links to the existing account with that email.
  3. Otherwise, pending invitations for that email create the account with their memberships.
  4. Otherwise, when exactly one tenant lists the email's domain in Allowed email domains, the person joins it as a viewer.
  5. Otherwise, there is no account: unknown people never get one by default.

Disabled accounts cannot sign in. Each person can see where they are signed in and sign other devices out under Your sessions in the account menu.

Worker and OpenTofu runner

VariableTypeDefaultDescription
WORKER_CONCURRENCYinteger from 1 to 644Deployment jobs one worker processes in parallel.
DEPLOY_LIMIT_PER_TENANTinteger, 0 for no limit5Deployments of one tenant running at once, across all workers. Others wait in the queue.
DEPLOY_LIMIT_PER_PROVIDER_REGIONinteger, 0 for no limit20Deployments touching one provider region at once, across all workers. Each cloud target also has its own limit.
HEALTH_CHECK_INTERVAL_SECONDSinteger, at least 1030Interval between health monitor ticks.
DRIFT_CHECK_INTERVAL_MINUTESinteger, at least 0360Interval between drift scans on real providers (one OpenTofu plan per applied resource). 0 turns scans off.
DNS_RESOLVERScomma separated addressessystem resolverDNS servers the worker asks when it verifies custom domains, for example 1.1.1.1,8.8.8.8. Set it when the system resolver is private and could hide the records customers create.
TOFU_IMAGEstringghcr.io/opentofu/opentofu:1.12.7Image for runner containers.
TOFU_MODULES_DIRpathModule library on the worker host, mounted read only into runners.
TOFU_MODULES_IN_IMAGEbooleanfalseThe modules are baked into TOFU_IMAGE, so nothing is mounted.
TOFU_WORK_DIRpathWhere the worker writes the working directory of each resource.
TOFU_WORK_VOLUMEstringFor a worker that runs in a container: a named volume mounted at TOFU_WORK_DIR and passed on to runners.
TOFU_PLUGIN_CACHE_VOLUMEstringorkstage-tofu-pluginsNamed volume that runners share as the provider plugin cache.
TOFU_DOCKER_NETWORKstringDocker network for runner containers, so they can reach an emulator by name.
TOFU_TIMEOUT_MINUTESinteger from 1 to 24045Hard time limit for one OpenTofu command.
AWS_ROLE_SESSION_MINUTESinteger from 15 to 72060Length of the AWS sessions OrkStage requests when it assumes a deployment role. Each OpenTofu run gets credentials that outlive TOFU_TIMEOUT_MINUTES, so keep this above it; above 60, raise the role's MaxSessionDuration too.
AWS_EMULATOR_ENDPOINTURLEmulator endpoint as seen from inside containers, for example http://ministack:4566.

Email

VariableTypeDefaultDescription
SMTP_HOSTstringlocalhostSMTP server.
SMTP_PORTinteger1025SMTP port (Mailpit in local development).
SMTP_SECUREbooleanfalseUse TLS from the start of the connection.
SMTP_USER, SMTP_PASSWORDstringnoneCredentials for mail servers that require them.
EMAIL_FROMstringOrkStage <noreply@example.local>Sender address.
EMAIL_TRANSPORTsmtp or sessmtpses sends through Amazon SES v2 with the worker's own AWS credentials and AWS_REGION; EMAIL_FROM must be a verified identity.
EMAIL_RATE_LIMIT_PER_HOURinteger from 1 to 1000030Notification emails one person receives per hour at most; the rest stay in the console.

Secrets and integrations

VariableTypeDefaultDescription
SECRETS_AWS_REGIONstringus-east-1Default region for aws-sm:// references given by name. ARNs carry their own region.
SECRETS_AWS_ENDPOINTURLSecrets Manager endpoint override for emulators, as seen from the API and the worker.
ENCRYPTION_KEYbase64, 32 bytesEncrypts secrets the platform must read back, such as webhook signing secrets. Required in production. Generate it with openssl rand -base64 32.
WEBHOOK_ALLOW_PRIVATEbooleanfalseAllows http:// webhook URLs and URLs on private networks. For local development only; refused in production.

env:// references cannot read the platform's own configuration (DATABASE_URL, REDIS_URL, SESSION_SECRET, ENCRYPTION_KEY, ORKSTAGE_LICENSE_KEY and anything starting with OIDC_, SMTP_, AWS_, TOFU_, API_, WEB_, APP_ or NODE_). Give target credentials their own names, for example ORK_AZURE_CREDENTIALS.

See Secret references.

Rate limits behind proxies

Rate limit counters live in Redis, so they hold across every API instance. Signed in requests are counted per session or API key. Sign in routes are counted per client address, which is only as trustworthy as the proxy that records it: put a load balancer or reverse proxy that appends the client address to X-Forwarded-For (an AWS ALB, nginx with proxy_add_x_forwarded_for) in front of the console, and leave TRUST_PROXY_HOPS at 1. The console's own proxy passes an incoming X-Forwarded-For through unchanged, so without such a proxy a client can pick the address the API sees for sign in limits. If the API is exposed directly, set TRUST_PROXY_HOPS=0.

Licensing and observability

VariableTypeDefaultDescription
ORKSTAGE_LICENSE_KEYstringEnterprise license key (it starts with orkstage-license.v1.). Empty means Community edition.
OTEL_EXPORTER_OTLP_ENDPOINTURLOpenTelemetry export (OTLP over HTTP) of traces and metrics from the API and the worker. Empty: off. See Observability.

Console

VariableDefaultDescription
API_INTERNAL_URLhttp://localhost:4000API origin (no path) that the console forwards /api/* to, for example http://api:4000. The console resolves its rewrites when it is built, so set this variable at build time.

Seed

The seed runs after migrations (the migrate service, or pnpm db:seed). It is idempotent.

VariableDefaultDescription
PLATFORM_OWNER_EMAILnoneCreates this user as the platform owner, or gives an existing user that role. There is no development sign in in production, so this is how the first administrator is created: they sign in with SSO using this email, which the provider must report as verified. Without it, a production seed warns that nobody can administer the platform.
ORGANIZATION_NAMEOrganizationName of the organization created on the first run, when none exists.
SEED_DEMO_DATAtrue, except with NODE_ENV=productionAdds the demo: simulated cloud targets, sample images, the Acme and Globex tenants and their users. Without it, the seed writes only plans, built in and marketplace templates, the organization and the platform owner.

Production safety checks

With NODE_ENV=production, startup fails when any of these is true:

  • AUTH_DEV_LOGIN_ENABLED is true.
  • ENCRYPTION_KEY is missing.
  • WEBHOOK_ALLOW_PRIVATE is true.
  • SESSION_SECRET still starts with change-me.

On this page