Env vars
Environment variables used to configure a self-hosted Proliferate deployment.
All configuration for a self-hosted Proliferate server lives in one file:
.env.static, in the deploy directory (/opt/proliferate/server/deploy when
you used the guided installer; the
extracted proliferate-deploy bundle otherwise). The installer generates it
for you on first run; if you set the stack up
manually instead, create it
once from the template that ships with each release:
bootstrap.sh reads .env.static, validates it with preflight.sh,
generates any missing secrets, and derives a .env.runtime file that the
containers actually load. Edit .env.static, never .env.runtime, then run
./update.sh to apply changes. update.sh regenerates .env.runtime and
restarts the stack; it also pulls the image for your configured tag, which is
a no-op when you pin a version. Rerunning ./bootstrap.sh applies the same
configuration without pulling; both are safe to rerun at any time.
The server ignores environment variables it does not recognize. Treat anything not in the template or on this page as unsupported: a typo or a removed override is silently ignored rather than raised as an error.
The required minimum
Three variables must be set before first bootstrap:
| Variable | What to set |
|---|---|
SITE_ADDRESS | Your public DNS name, for example proliferate.company.com. A scheme is optional; https is assumed when you leave it off. |
PROLIFERATE_TELEMETRY_MODE | self_managed. |
PROLIFERATE_SERVER_IMAGE_TAG | The server version you run: a pinned release tag, or stable. |
Three secrets should be left blank; the first ./bootstrap.sh run generates
strong values and persists them:
API_BASE_URL and FRONTEND_BASE_URL are both derived from SITE_ADDRESS by
bootstrap when you do not set them, which is right for almost every install:
one public URL serves the API and the Web app. API_BASE_URL is the
canonical public URL the server uses to build absolute callback URLs and the
configuration it pushes to workspaces; FRONTEND_BASE_URL is the public
origin of the Web app. Set either explicitly only when its public URL differs
from https://<SITE_ADDRESS>; an explicit value always wins, and setting one
does not disturb the other's derivation. An explicit http://localhost
SITE_ADDRESS keeps both URLs on HTTP.
Core
| Variable | Required | Purpose |
|---|---|---|
SITE_ADDRESS | Yes | Public hostname Caddy serves, with or without a scheme. Point DNS at the host before first startup so Let's Encrypt can issue a certificate. Both the API and, by default, the Web app answer here. |
API_BASE_URL | No | Canonical public API base URL, used for absolute auth callback generation. Derived from SITE_ADDRESS by bootstrap when unset; an explicit value wins. |
FRONTEND_BASE_URL | No | Public origin of the Web app. Derived from SITE_ADDRESS by bootstrap when unset, same-origin with the API; an explicit value wins. |
WEB_DIST_DIR | No | Directory the server serves the compiled Web app from. The shipped Compose file sets it to /app/web-dist, where the server image bakes the compiled distribution, so Web serving is on by default. Set to empty to run API-only. |
PROLIFERATE_TELEMETRY_MODE | Yes | self_managed on self-hosted installs. See Telemetry below. |
PROLIFERATE_SERVER_IMAGE | No | Server image source. Default ghcr.io/proliferate-ai/proliferate-server. |
PROLIFERATE_SERVER_IMAGE_TAG | Yes | The version you track: a pinned release tag for change-controlled environments, or stable. See Updates & versioning. |
POSTGRES_DB | No | Bundled Postgres database name. Default proliferate. |
POSTGRES_USER | No | Bundled Postgres user. Default proliferate. |
POSTGRES_PASSWORD | Leave blank | Secret. Auto-generated and persisted on first bootstrap. |
JWT_SECRET | Leave blank | Secret. Signs sessions and OAuth state. Auto-generated on first bootstrap. |
CLOUD_SECRET_KEY | Leave blank | Secret. Encrypts stored credentials at rest and signs cloud workspace flows. Auto-generated on first bootstrap. |
DATABASE_URL | Generated | Derived into .env.runtime from the POSTGRES_* values, pointing at the bundled db service. Set it yourself only if you run an external Postgres. |
CORS_ALLOW_ORIGINS | Preset | Browser and desktop webview origins allowed to call the API. The template default covers the desktop app; extend it only if you know you need to. |
PROLIFERATE_PUBLIC_HEALTHCHECK_URL | No | Optional public endpoint check that runs after the local API health check passes. The AWS stack sets it automatically. |
AWS_REGION | No | Only needed when pulling the server image from a private ECR registry. |
Sign-in
Email and password sign-in is on by default and needs no configuration. The
desktop app asks your server which methods are available
(GET /auth/desktop/methods) and shows the email and password form as the
default whenever GitHub OAuth is not configured.
| Variable | Required | Purpose |
|---|---|---|
PASSWORD_AUTH_ENABLED | No | Default true. Set to false to disable the whole password surface: password login, credential management, and account registration (the /register page and POST /auth/password/register return 404). See Email & password. |
GitHub sign-in (optional)
| Variable | Required | Purpose |
|---|---|---|
GITHUB_OAUTH_CLIENT_ID | No | Client ID of a GitHub OAuth app, if you want desktop GitHub sign-in. Set the app's callback URL to <API_BASE_URL>/auth/github/callback (the same URL for desktop, web, and mobile). |
GITHUB_OAUTH_CLIENT_SECRET | No | Secret. Client secret of the same app. |
See GitHub auth for the walkthrough.
OIDC SSO (optional)
| Variable | Required | Purpose |
|---|---|---|
SSO_ENABLED | No | Enables deployment SSO. Default false. |
SSO_OIDC_ISSUER_URL | With SSO | Your identity provider's OIDC issuer URL; endpoints are resolved via discovery. |
SSO_OIDC_CLIENT_ID | With SSO | OIDC client ID registered with your provider. |
SSO_OIDC_CLIENT_SECRET | With SSO | Secret. OIDC client secret. |
SSO_LOGIN_POLICY | No | optional (default) shows SSO next to other methods. Setting required is rejected by the server; enforced SSO-only login is planned. |
SSO_JIT_POLICY | No | Just-in-time provisioning for users who sign in via SSO without an invitation. Default disabled. |
SSO_ALLOWED_DOMAINS | No | Comma-separated email domains allowed for SSO just-in-time provisioning. |
SSO_DEFAULT_ROLE | No | Role granted to just-in-time provisioned users. Default member. |
SSO_DISPLAY_NAME | No | Label shown on the SSO sign-in button. Default Company SSO. |
SSO_OIDC_SCOPES | No | Requested scopes. Default openid email profile. |
SSO_OIDC_CALLBACK_BASE_URL | No | Override when the SSO callback base URL differs from API_BASE_URL. |
SSO_OIDC_ALLOW_PRIVATE_PROVIDER_URLS | No | Default false. By default the issuer and every discovered OIDC endpoint must be HTTPS and resolve to a public IP (an SSRF guard). Set true only to point at an internal/private/http identity provider; this disables that guard for all OIDC provider URLs. |
For providers without OIDC discovery, explicit endpoint overrides exist:
SSO_OIDC_DISCOVERY_URL,
SSO_OIDC_AUTHORIZATION_ENDPOINT,
SSO_OIDC_TOKEN_ENDPOINT, SSO_OIDC_JWKS_URI, and
SSO_OIDC_USERINFO_ENDPOINT. Every SSO_* variable also accepts a
PROLIFERATE_ prefix (for example PROLIFERATE_SSO_ENABLED); both names
read the same setting.
Single-org mode and access control
Self-hosted installs run in single-org mode: the whole instance is one
organization, claimed once at https://<SITE_ADDRESS>/setup with the setup
token that bootstrap.sh prints. The default is derived, so a self-hosted
install needs no configuration here: single-org mode is on whenever
PROLIFERATE_TELEMETRY_MODE is anything other than hosted_product.
| Variable | Required | Purpose |
|---|---|---|
SINGLE_ORG_MODE | No | Explicit override for the membership mode; an explicit value wins over the derived default. Effectively fixed once the instance is claimed. |
ADMIN_EMAILS | Recommended | Comma-separated admin floor: these emails always hold at least the admin role, asserted at account creation and at every sign-in. This is also lockout recovery: add your email, restart the server, sign in. Removing an email from the list never demotes anyone, and the last admin is protected. Listed emails are reinstated as admin at their next sign-in even after removal from the organization, so offboarding a listed user means removing them from this list too and restarting. |
ALLOWED_EMAIL_DOMAINS | No | Comma-separated email domains invited users must belong to before they can self-register. A gate on top of invitations, never a grant: registration requires the invitation token from the invite link (POST /auth/password/register rejects anything else with a uniform 403), and it assigns no roles. |
PROLIFERATE_SETUP_TOKEN_FILE | No | Path inside the api container where the plaintext first-run setup token is written. Default /var/lib/proliferate/setup/setup-token, on a named volume so restarts do not rotate it. Never served over HTTP; bootstrap.sh prints it for you. |
RESEND_API_KEY | No | Secret. Resend API key for invitation email delivery. When set, invite emails link straight to the /register page with the invitation token prefilled. Invitations work without any email provider: the admin shares the invite link with the Copy invite link action in the members list. |
RESEND_FROM_EMAIL | No | Sender address for invitation emails, on a domain you have verified with Resend. |
Cloud sandboxes add-on
The cloud sandboxes add-on is
coming soon. Its variables (the sandbox provider credentials, GITHUB_APP_*,
and the runtime-binary paths read by install-runtime.sh) still exist in the
deploy tooling but will be documented when the add-on launches. A current
install leaves all of them unset; preflight.sh flags a half-configured
provider credential pair.
Model gateway add-on
Only needed with the optional model gateway. Without it, users bring their own agent subscriptions and no gateway variables are set. Budgets are enforced at the gateway; self-hosted installs have no credits or billing UI.
The standard Compose stack can run the gateway for you: litellm and its own
Postgres database ship as an opt-in service group, off unless you turn on the
agent-gateway Compose profile.
Older copies of .env.production.example have an AGENT_GATEWAY_BIFROST_*
block left over from before the gateway moved to LiteLLM. The server does not
read those names at all; per the callout above, it just ignores them. Delete
that block and use only the AGENT_GATEWAY_LITELLM_* and LITELLM_*
variables below.
| Variable | Required | Purpose |
|---|---|---|
AGENT_GATEWAY_ENABLED | No | Enables the gateway integration. Default false. |
AGENT_GATEWAY_LITELLM_BASE_URL | With the gateway | Private LiteLLM admin URL the Proliferate server calls to mint and manage virtual keys. http://litellm:4000 for the bundled service; keep it unreachable from the public internet. |
AGENT_GATEWAY_LITELLM_PUBLIC_BASE_URL | With the gateway | Public LiteLLM inference URL written into sandbox configuration; this is what agents actually call. |
AGENT_GATEWAY_LITELLM_MASTER_KEY | With the gateway | Secret. Master key the server uses to manage virtual keys; must match LITELLM_MASTER_KEY on the LiteLLM container. Never sent to sandboxes. |
AGENT_GATEWAY_LITELLM_TIMEOUT_SECONDS | No | Timeout for calls to the LiteLLM admin API. Default 30. |
AGENT_GATEWAY_DEFAULT_USER_BUDGET_USD | No | Default monthly USD cap on a personal virtual key. Default 5. |
AGENT_GATEWAY_DEFAULT_ORG_BUDGET_USD | No | Default cap on organization-wide gateway usage (shared and automation sandboxes). Default 0, which LiteLLM treats as uncapped. |
Bundled LiteLLM service (optional)
Only needed if you use the bundled litellm service instead of pointing the
variables above at a LiteLLM instance you run elsewhere.
| Variable | Required | Purpose |
|---|---|---|
LITELLM_MASTER_KEY | With the bundled service | Secret. Master key set on the LiteLLM container itself; must match AGENT_GATEWAY_LITELLM_MASTER_KEY. |
LITELLM_POSTGRES_PASSWORD | With the bundled service | Secret. Password for the bundled litellm-db Postgres instance. |
LITELLM_POSTGRES_DB / LITELLM_POSTGRES_USER | No | Defaults to litellm / litellm. |
ANTHROPIC_API_KEY / OPENAI_API_KEY / XAI_API_KEY | With the bundled service | Secret. Provider keys passed into the LiteLLM container's environment. Set only the providers you use. |
PROLIFERATE_LITELLM_IMAGE / PROLIFERATE_LITELLM_IMAGE_TAG | No | Override the LiteLLM image or tag. Default ghcr.io/proliferate-ai/proliferate-litellm:stable. |
bootstrap.sh and update.sh bring litellm/litellm-db up (and wait for
litellm to report healthy) automatically whenever AGENT_GATEWAY_ENABLED=true
— there is no separate profile command to remember. Turning the gateway
off is the one case that still needs a manual step: setting
AGENT_GATEWAY_ENABLED=false and running update.sh stops managing the
containers going forward, but does not stop already-running ones. See
Model gateway
for the exact docker compose --profile agent-gateway down command.
Instance identity & support
Surfaced on the public capability contract (GET /meta) so the desktop
renders a self-hosted server as itself, not as Proliferate Cloud. All
optional; every field also accepts a PROLIFERATE_ prefix.
| Variable | Required | Purpose |
|---|---|---|
INSTANCE_NAME | No | Display name shown in the desktop's "Connected to <name>" identity line. Empty falls back to the connected server's host name. |
INSTANCE_LOGO_URL | No | Absolute https:// logo URL. Accepted and returned by /meta today; the desktop does not render it in any surface yet. |
INSTANCE_SUPPORT_EMAIL | No | Operator support email. Empty means the desktop offers no support-email affordance for this server (never the vendor's). |
INSTANCE_SUPPORT_URL | No | Operator support or docs URL, shown alongside the email when set. |
Telemetry
| Variable | Required | Purpose |
|---|---|---|
PROLIFERATE_TELEMETRY_MODE | Yes | One of local_dev, self_managed, hosted_product. Self-hosted installs run self_managed; vendor telemetry only ever activates on hosted_product. |
PROLIFERATE_ANONYMOUS_TELEMETRY_DISABLED | No | Set to 1 for zero telemetry: no anonymous heartbeat leaves your server. |
PROLIFERATE_ANONYMOUS_TELEMETRY_ENDPOINT | No | Where the daily anonymous heartbeat is sent. Default https://app.proliferate.com/api/v1/telemetry/anonymous. |
Exactly what is sent, byte for byte, is documented in Telemetry & privacy.
Background jobs
The template also contains CELERY_* and REDBEAT_* variables. They are
dormant: automations and background jobs are not available on self-hosted
deployments yet, because the worker tier does not ship in v1. Leave them at
their template defaults.
Everything else
The template ships a few more optional integrations at safe defaults: cloud
MCP connectors (CLOUD_MCP_*), transactional email (CUSTOMERIO_*), AI
session-title generation (ANTHROPIC_API_KEY), and vendor observability
(SENTRY_*, which is inert outside hosted_product mode). Leave them at
their defaults unless a page in these docs tells you otherwise.
The only client-side configuration is the desktop config file
~/.proliferate/config.json with apiBaseUrl and the optional
telemetryDisabled; see Connect the desktop
app.