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
Variable
Default
Meaning and rules
DATABASE_URL
required
Postgres connection string, such as postgres://opend:secret@db:5432/opend.
PUBLIC_URL
http://localhost:3000
Where 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.
PORT
3000
Port to listen on: an integer from 0 to 65535.
HOST
0.0.0.0
Interface to listen on.
SESSION_SECRET
required
Signs 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_KEY
derived from SESSION_SECRET
Seals 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_ENV
development (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_REPO
none
The 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_TOKEN
none
Bearer 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
Variable
Default
Meaning and rules
GITHUB_WEBHOOK_SECRET
none
The 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_ID
none
The 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_KEY
none
The 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_URL
https://api.github.com
API base URL, for GitHub Enterprise Server, such as https://github.example.com/api/v3. Must be a URL.
OPEND_GITHUB_BROKER_URL
none
Managed 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_SECRET
none
This instance's bearer token for the broker. At least 16 characters.
OPEND_HOSTING_URL
none
Managed 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_TOKEN
none
This site's bearer token for the site API. At least 16 characters.
OPEND_GITHUB_INSTALL_URL
none
Managed 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
Variable
Default
Meaning and rules
OIDC_ISSUER
none
The OpenID Connect issuer URL. Requires OIDC_CLIENT_ID and OIDC_CLIENT_SECRET.
OIDC_CLIENT_ID
none
The client id registered with the provider.
OIDC_CLIENT_SECRET
none
The client secret.
OIDC_SCOPES
openid email profile
Scopes to request, space-separated. Keep email: readers are matched by verified email.
OIDC_DISPLAY_NAME
your company account
How 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_ICON
key (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_ID
none
Adds 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_SECRET
none
The matching client secret.
GITHUB_WEB_URL
https://github.com
Where GitHub sign-in sends readers, for GitHub Enterprise Server. Must be a URL.
OPEND_GITHUB_COLLABORATOR_ORG
off
An 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_STAFF
off
Flag. Readers added by OPEND_GITHUB_COLLABORATOR_ORG are staff: they see everything, conditions marked. Needs OPEND_GITHUB_COLLABORATOR_ORG.
OPEND_DEV_LOGIN
off
Flag. 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_URL
none
The 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.
OPEND_SOURCE_LINKS
off
Flag. Adds View source on GitHub to topic pages of a repository cloned from https://github.com, pointing at the built commit. Every viewer sees it, anonymous visitors of a public site too, so turn it on only when the repository is public or every reader may read it.
Blob storage
Variable
Default
Meaning 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_BUCKET
none
Bucket 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_ENDPOINT
none
Service URL, such as https://s3.us-east-1.amazonaws.com. Must be a URL.
S3_ACCESS_KEY_ID
none
Access key id.
S3_SECRET_ACCESS_KEY
none
Secret access key.
S3_REGION
auto
Region. Most S3-compatible services accept auto.
S3_FORCE_PATH_STYLE
off
Flag. Address the bucket as /<bucket>/<key> instead of <bucket>.<host>, for MinIO and similar services.
S3_PREFIX
none
Prepended to every key, such as opend/, to share a bucket.
Embedded help
Variable
Default
Meaning and rules
OPEND_EMBED_SECRET
none
Shared secret host apps sign embed tokens with. At least 32 characters. Set together with OPEND_EMBED_ORIGINS; without both, embedding is off.
OPEND_EMBED_ORIGINS
none
Comma-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_URL
none
The 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.
Variable
Default
Meaning and rules
OPEND_FLEET_KEY
none (required)
Seals each site's settings in the registry. At least 32 characters. Changing it makes stored sites unreadable.
OPEND_FLEET_TOKEN
none (required)
Bearer token for the fleet admin API. At least 32 characters.
OPEND_FLEET_HOST
none (required)
The fleet's own host name, where the admin API answers. No site may use it.
OPEND_FLEET_MAX_SITES
200
How 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_CONCURRENCY
2
Build jobs the fleet worker runs at once, across all sites. One site never runs two at a time.
On 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_DAYS
180
Days 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.
Variable
Default
Meaning and rules
OPEND_CHROMIUM_PATH
the browser Playwright installed (the image sets /usr/bin/chromium)
Path of the Chromium binary that prints PDFs.
OPEND_CHROMIUM_SANDBOX
off
Set 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.