Skip to content

Environment variable reference

Every setting of opend-server, with its default and the rules it is checked against at start-up.

How settings are read

  • All settings are environment variables; nothing is baked into the image. Give the web service and the worker the same values.
  • Every command (serve, worker, migrate, seed) checks the whole set at start-up and refuses to start with a list of every problem.
  • An empty value counts as unset. So does an unresolved reference variable on Railway.
  • Flags are on when set to 1 or true, and off otherwise.
  • The web editor has its own settings, listed in Run the web editor.
  • Some settings can instead be changed by staff in the admin console (sign-in, the GitHub connection, editor links). A variable that is set always wins over the console, which then shows the setting read-only. See Console settings, environment variables and the secret key.

Core

VariableDefaultMeaning and rules
DATABASE_URLrequiredPostgres connection string, such as postgres://opend:secret@db:5432/opend.
PUBLIC_URLhttp://localhost:3000Where readers reach the site. Must be a URL; a trailing slash is removed. It is the OIDC callback base, the audience of embed tokens, and the base of absolute links in PDFs and the JSON API. When it starts with https://, cookies are marked Secure.
PORT3000Port to listen on: an integer from 0 to 65535.
HOST0.0.0.0Interface to listen on.
SESSION_SECRETrequiredSigns session cookies. At least 32 characters. Changing it signs every reader out. Without OPEND_SECRET_KEY, the key that seals stored secrets is derived from it, so changing it also makes those secrets unreadable until they are entered again.
OPEND_SECRET_KEYderived from SESSION_SECRETSeals the secrets the admin console stores (client secrets, the GitHub App's private key and webhook secret) with AES-256-GCM. At least 32 characters. Set it to rotate SESSION_SECRET freely; give the web, worker and editor services the same value. See Console settings, environment variables and the secret key.
NODE_ENVdevelopment (the image sets production)With production, the server refuses to start with OPEND_DEV_LOGIN, and sign-in refuses an http:// OIDC issuer.
OPEND_SITE_REPOnoneThe repository the site serves, as owner/name, when more than one is registered. Without it, the site works only while exactly one repository is registered.
OPEND_ADMIN_TOKENnoneBearer token for the admin API. At least 24 characters. Without it the admin API does not exist. The admin console at /admin does not need it: staff readers sign in.

GitHub

VariableDefaultMeaning and rules
GITHUB_WEBHOOK_SECRETnoneThe secret set on the repository's or GitHub App's webhook. The webhook secret of the app connected in the admin console is accepted as well, since that app signs its own deliveries with it; without either, /webhooks/github answers 503. In managed hosting, the control plane re-signs forwarded deliveries with this value.
GITHUB_APP_IDnoneThe GitHub App's id, for private repositories and commit statuses. Set together with GITHUB_APP_PRIVATE_KEY. Without it, Connect GitHub in the admin console creates and stores an app instead (Connect GitHub from the admin console). Not together with OPEND_GITHUB_BROKER_URL.
GITHUB_APP_PRIVATE_KEYnoneThe App's private key, PEM, PKCS#1 as GitHub issues it or PKCS#8. Literal \n sequences are turned into line breaks, so the key fits on one line. Set together with GITHUB_APP_ID.
GITHUB_API_URLhttps://api.github.comAPI base URL, for GitHub Enterprise Server, such as https://github.example.com/api/v3. Must be a URL.
OPEND_GITHUB_BROKER_URLnoneManaged hosting only: the control plane's token broker, such as https://control.example/broker/v1. The worker, poller and editor get installation tokens from it (read for builds, write for the editor and commit statuses) instead of a GitHub App of their own, and the admin console's repository picker lists what it returns. Set by the hosting provider, together with OPEND_GITHUB_BROKER_SECRET.
OPEND_GITHUB_BROKER_SECRETnoneThis instance's bearer token for the broker. At least 16 characters.
OPEND_HOSTING_URLnoneManaged hosting only: the hosting provider's site API, such as https://control.example/site/v1. With it the admin console's Custom domain page sets the site's domain and shows the DNS records to add (Serve your site at your own domain); without it the page explains that the domain is PUBLIC_URL. Independent of how the site reaches GitHub. Set by the hosting provider, together with OPEND_HOSTING_TOKEN. When neither is set, a broker at …/broker/v1 implies …/site/v1 with the broker secret.
OPEND_HOSTING_TOKENnoneThis site's bearer token for the site API. At least 16 characters.
OPEND_GITHUB_INSTALL_URLnoneManaged hosting: the shared GitHub App's installation page, such as https://github.com/apps/opend/installations/new. The admin console's Connect GitHub button links to it.

Reader sign-in

VariableDefaultMeaning and rules
OIDC_ISSUERnoneThe OpenID Connect issuer URL. Requires OIDC_CLIENT_ID and OIDC_CLIENT_SECRET.
OIDC_CLIENT_IDnoneThe client id registered with the provider.
OIDC_CLIENT_SECRETnoneThe client secret.
OIDC_SCOPESopenid email profileScopes to request, space-separated. Keep email: readers are matched by verified email.
OIDC_DISPLAY_NAMEyour company accountHow the sign-in page names the OIDC provider: Sign in with name. At most 60 characters. With GitHub, the button shows GitHub's mark.
OIDC_ICONkey (github when the display name is GitHub)The OIDC button's icon: key or github. Managed hosting signs readers in with GitHub through its own OIDC provider and sets github.
GITHUB_OAUTH_CLIENT_IDnoneAdds Sign in with GitHub. The client id of the GitHub App (or an OAuth App). The same name and value as the web editor's, so one GitHub App serves both. Set together with GITHUB_OAUTH_CLIENT_SECRET.
GITHUB_OAUTH_CLIENT_SECRETnoneThe matching client secret.
GITHUB_WEB_URLhttps://github.comWhere GitHub sign-in sends readers, for GitHub Enterprise Server. Must be a URL.
OPEND_GITHUB_COLLABORATOR_ORGoffAn org slug. A GitHub user with write, maintain or admin access to the site's repository, whose primary email GitHub has verified and no reader uses yet, becomes a reader of this org on first sign-in. Needs GitHub sign-in and GITHUB_APP_ID, and the repository registered with its installation id. The org must exist.
OPEND_GITHUB_COLLABORATOR_STAFFoffFlag. Readers added by OPEND_GITHUB_COLLABORATOR_ORG are staff: they see everything, conditions marked. Needs OPEND_GITHUB_COLLABORATOR_ORG.
OPEND_DEV_LOGINoffFlag. Lists every registered reader under Demo readers on the sign-in page, where anyone can sign in as any of them, for evaluation without an identity provider. Refused when NODE_ENV=production. Staff can turn it off (and on again) in the admin console, but never on without this flag.
EDITOR_PUBLIC_URLnoneThe web editor's address, such as https://edit.docs.example. Signed-in staff readers get an Edit this page link on topic pages, opening the topic's source file in the editor. The editor still decides who may edit. Must be a URL. Without it, the address set in the admin console (Editor) is used.

Blob storage

VariableDefaultMeaning and rules
BLOB_DIR./data/blobs (the image sets /data/blobs)Folder for images, themes and PDFs when no bucket is configured. Web and worker must share it.
S3_BUCKETnoneBucket name. Setting it switches to S3-compatible storage, and then S3_ENDPOINT, S3_ACCESS_KEY_ID and S3_SECRET_ACCESS_KEY are required too: all four or none.
S3_ENDPOINTnoneService URL, such as https://s3.us-east-1.amazonaws.com. Must be a URL.
S3_ACCESS_KEY_IDnoneAccess key id.
S3_SECRET_ACCESS_KEYnoneSecret access key.
S3_REGIONautoRegion. Most S3-compatible services accept auto.
S3_FORCE_PATH_STYLEoffFlag. Address the bucket as /<bucket>/<key> instead of <bucket>.<host>, for MinIO and similar services.
S3_PREFIXnonePrepended to every key, such as opend/, to share a bucket.

Embedded help

VariableDefaultMeaning and rules
OPEND_EMBED_SECRETnoneShared secret host apps sign embed tokens with. At least 32 characters. Set together with OPEND_EMBED_ORIGINS; without both, embedding is off.
OPEND_EMBED_ORIGINSnoneComma-separated origins allowed to frame the help panel and call the JSON API, such as https://console.example.com,http://localhost:5173. Each must be http or https with no path or trailing slash.
OPEND_MCP_URLnoneThe address of the managed MCP connector (one for every site), shown on the admin console's API & AI page so staff can connect AI assistants. Managed hosting sets it; see Public API and AI assistants.

Fleet mode

Read only by opend-server fleet serve and opend-server fleet worker, which run many sites from one deployment (Run many sites from one deployment). The fleet also reads DATABASE_URL, PORT, HOST, BLOB_DIR and the S3_* variables for itself and every site. Each site's other settings come from its registry entry, not from the environment.

VariableDefaultMeaning and rules
OPEND_FLEET_KEYnone (required)Seals each site's settings in the registry. At least 32 characters. Changing it makes stored sites unreadable.
OPEND_FLEET_TOKENnone (required)Bearer token for the fleet admin API. At least 32 characters.
OPEND_FLEET_HOSTnone (required)The fleet's own host name, where the admin API answers. No site may use it.
OPEND_FLEET_MAX_SITES200How many site apps (docs and editor counted separately) stay running at once. The least recently used are closed beyond it and restart on their next request.
OPEND_FLEET_REDIRECTS(none)Hosts under the fleet's domain answered with a permanent redirect instead of a site, keeping the path and query: comma-separated host=https://origin pairs, such as www.opend.app=https://opend.app.
OPEND_FLEET_WORKER_CONCURRENCY2Build jobs the fleet worker runs at once, across all sites. One site never runs two at a time.

Analytics and feedback

See Docs analytics and reader feedback for what is recorded.

VariableDefaultMeaning and rules
OPEND_ANALYTICSonOn unless set to 0, false, off or no. Off records no page views, searches or feedback and hides the "Was this page helpful?" form. The analytics admin routes still answer with what was recorded before.
OPEND_ANALYTICS_RETENTION_DAYS180Days to keep analytics rows: a whole number from 1 to 3650. The worker deletes older rows when it starts and every six hours after, even with analytics off. opend-server purge-analytics does it on demand.

PDF printing

Read by the PDF renderer when it first starts Chromium.

VariableDefaultMeaning and rules
OPEND_CHROMIUM_PATHthe browser Playwright installed (the image sets /usr/bin/chromium)Path of the Chromium binary that prints PDFs.
OPEND_CHROMIUM_SANDBOXoffSet to exactly 1 to run Chromium with its own sandbox, where the runtime allows the namespaces it needs.

Docker Compose only

POSTGRES_PASSWORD (default opend) and OPEND_PORT (default 3000) are read by deploy/docker-compose.yml, not by the server.