Environment Variables
Configure runtime modes, Redis connections, persistence, authentication, integrations, and telemetry.
For source-based runs, copy the repository's
.env.example to .env and replace
its placeholders. Shell variables take precedence over dotenv values. Restart the API after
changing configuration.
For Docker, explicitly pass settings with -e, --env-file, or the container's Compose
environment block. A Compose substitution file does not automatically become container
configuration; see Docker configuration.
Core runtime
| Variable | Default | Purpose |
|---|---|---|
NODE_ENV | Unset | development, test, or production; set production for deployments. Production images already set it. |
PORT | 3001 outside production; 3000 in production | API listening port. |
APP_BASE_URL | http://localhost:5173 | Public app origin used by auth, invitations, and MCP. Set explicitly for any deployed origin. |
VITE_PUBLIC_APP_URL | Unset | Browser app URL fallback; normally match APP_BASE_URL. Vite embeds client environment values at build time. |
DURABULL_AUTHLESS | false | Bypass login and grant owner access. Use only in trusted local/private environments. |
DURABULL_ENV_CONNECTIONS | false | Manage Redis connections through environment variables instead of UI/API create/edit/delete. |
TRUST_PROXY | false | Honor forwarding headers for rate-limit keys; enable only behind a proxy that controls those headers. Cloud enables this behavior automatically. |
DISABLE_RATE_LIMIT | false | Disable all in-memory API and MCP rate limits. Keep unset in production. |
Boolean settings in the shared environment schema accept true/false, 1/0, yes/no,
and on/off. Use true or false in deployment configuration for clarity.
Authentication
| Variable | Requirement | Purpose |
|---|---|---|
BETTER_AUTH_SECRET | Authenticated deployments; required by the shipped self-hosted Compose file | Session and OAuth secret. Generate a long random value. |
GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET | Both needed for Google sign-in | Google OAuth credentials. |
GITHUB_OAUTH_CLIENT_ID, GITHUB_OAUTH_CLIENT_SECRET | Both needed for GitHub sign-in | GitHub OAuth credentials. |
MCP_AUTHLESS_BEARER_TOKEN | Required when authless and NODE_ENV=production | Bearer token for MCP only; does not protect the web UI or REST API. |
Email/password authentication is enabled without social providers. Register OAuth callbacks at
{APP_BASE_URL}/api/auth/callback/google and {APP_BASE_URL}/api/auth/callback/github. In normal
Vite development, the origin is http://localhost:5173.
Persistence and encryption
| Variable | Default / requirement | Purpose |
|---|---|---|
DATABASE_URL | Optional | Set to use PostgreSQL; empty or unset uses file-backed PGlite. |
DURABULL_PGLITE_DIR | data/pglite relative to the API working directory | PGlite storage directory; preserve it across restarts. |
DURABULL_REDIS_URL_ENCRYPTION_KEY | Required when saving or synchronizing Redis connections | 32-byte encryption key encoded as 64 hexadecimal characters or base64. |
DURABULL_SECRET_ENCRYPTION_KEY | Required for persisted integration/signing secrets | Separate 32-byte key for Linear OAuth tokens and webhook signing secrets. |
REDIS_URL | Optional | Redis URL used by development/seed scripts and as a workload fallback; does not configure an API connection by itself. |
DURABULL_POSTGRES_PORT | 55432 | Host port for the development Docker PostgreSQL service. Match DATABASE_URL. |
DURABULL_REDIS_PORT | 56379 | Host port for the development Docker Redis service. Match REDIS_URL. |
Generate each encryption key separately with openssl rand -hex 32, then paste the result into
configuration. Dotenv files do not evaluate $(...). Preserve the keys with your backups;
replacing a key without re-encrypting existing data makes that data unreadable.
Environment-managed Redis connections
Set DURABULL_ENV_CONNECTIONS=true and define one or more named connections:
| Variable | Default / requirement | Purpose |
|---|---|---|
DURABULL_REDIS_URL_<NAME> | At least one valid connection needed for queue operations | Redis URL (redis:// or rediss://). Names begin with a letter and use uppercase letters, digits, or underscores. |
DURABULL_REDIS_URL_<NAME>_ENVIRONMENT | development | development, staging, or production; invalid labels fall back to development. |
DURABULL_REDIS_URL_<NAME>_PREFIX | bull | BullMQ key prefix, matching your queues and workers. |
DURABULL_REDIS_URL_<NAME>_ALLOW_SELF_SIGNED_CERTS | false | Disable certificate-authority validation for this connection when the provider requires it. Use with rediss://. |
DURABULL_REDIS_URL_DEFAULT | First valid name alphabetically | Default connection key, such as MAIN. |
DURABULL_ENV_CONNECTIONS=true
DURABULL_REDIS_URL_MAIN=rediss://user:password@redis.example.com:6379/0
DURABULL_REDIS_URL_MAIN_ENVIRONMENT=production
DURABULL_REDIS_URL_MAIN_PREFIX=bull
DURABULL_REDIS_URL_DEFAULT=MAINReplace the example credentials and host. These connections still use encrypted database rows,
so DURABULL_REDIS_URL_ENCRYPTION_KEY is required.
Alerts and Redis health history
| Variable | Default | Purpose |
|---|---|---|
DURABULL_ALERT_ENABLED | true | Evaluate alert rules. Redis health history has its own collection toggle. |
DURABULL_ALERT_POLL_INTERVAL_MS | 60000 (minimum 5000) | Polling interval for queue alerts and Redis health sampling. |
DURABULL_ALERT_JOB_RESOLVE_INTERVAL_MS | 300000 (minimum 30000) | Interval for checking job-failure incidents for recovery. |
DURABULL_REDIS_HEALTH_HISTORY_ENABLED | true | Store Redis health samples for Analytics independently of alert evaluation. |
DURABULL_REDIS_HEALTH_RETENTION_DAYS | 30 (clamped to 1–30) | Redis health history retention. |
DURABULL_WEBHOOK_ALLOW_HTTP | false | Allow HTTP webhook targets for testing. Does not allow private or localhost targets. Development mode also permits HTTP. |
Email and Linear
| Variable | Default / requirement | Purpose |
|---|---|---|
RESEND_API_KEY | Optional | Send invitation and alert emails through Resend. |
EMAIL_FROM | Durabull <no-reply@durabull.io> | Sender address. Self-hosted Resend accounts should use their own verified domain. |
LINEAR_OAUTH_CLIENT_ID, LINEAR_OAUTH_CLIENT_SECRET | Both needed for Linear | OAuth application credentials. |
LINEAR_OAUTH_REDIRECT_URI | {APP_BASE_URL}/api/alerts/integrations/linear/callback | Callback override when the API has a different public origin. |
LINEAR_OAUTH_ACTOR | user | Use app only when the Linear application is configured for app actor authorization. |
Register the exact callback URL in Linear and set DURABULL_SECRET_ENCRYPTION_KEY before connecting.
See Linear Integration and
Webhook Notifications for setup and delivery behavior.
PostHog
| Variable | Default | Purpose |
|---|---|---|
POSTHOG_KEY | Unset | Send the full PostHog browser analytics stream to your project. |
POSTHOG_HOST | https://us.i.posthog.com | PostHog ingestion host, such as https://eu.i.posthog.com for EU Cloud. |
The web app obtains PostHog configuration from GET /api/app/config; no VITE_ prefix is needed.
The API proxies browser analytics through /ingest. Set POSTHOG_HOST to the ingestion host,
not your app's /ingest URL.
Anonymous usage telemetry
Production Durabull, including desktop and self-hosted builds, collects anonymous/pseudonymous
usage telemetry. Collection is disabled in development, test, and CI. Configuring POSTHOG_KEY
for your own project does not disable Durabull telemetry, and there is no product-level opt-out.
Durabull's sanitized telemetry includes feature and route usage, safe runtime context, booleans, enums, and aggregate count/duration buckets. It excludes Redis URLs, queue names, Redis key names, job data, logs, emails, names, organizations, hostnames, raw URLs, search patterns, stack traces, and raw error messages. This field restriction applies to the sanitized Durabull stream; your configured PostHog project receives its full browser analytics stream.
MCP analytics additionally records tool/resource names, OAuth stages, scope counts, client and protocol metadata, event times, outcomes, and durations. Where configured, hashed user, service-account, organization, client, connection, session, and request identifiers associate activity across requests. These are pseudonymous identifiers, not a guarantee of anonymity. The separate browser PostHog stream can include identified user and organization profiles, page URLs, interactions, and exception diagnostics. See the Privacy Policy for data uses, recipients, retention, and available controls.
Self-hosted instances forward sanitized batches to Durabull's existing cloud API. They do not need a separate collector service. These settings support forwarding and cloud collector operation:
| Variable | Purpose |
|---|---|
DURABULL_TELEMETRY_COLLECT_SECRET | HMAC signing secret for forwarded batches and collector verification. Forwarding is skipped when no signing secret is available. |
DURABULL_TELEMETRY_HMAC_SECRET | Dedicated HMAC secret for pseudonymous identifiers; not derived from BETTER_AUTH_SECRET. |
DURABULL_CLOUD | Enable Durabull Cloud collector behavior and trusted-proxy handling. Do not enable on an ordinary self-hosted instance. |
DURABULL_TELEMETRY_POSTHOG_KEY | Collector's Durabull telemetry destination; falls back to POSTHOG_KEY. |
DURABULL_TELEMETRY_POSTHOG_HOST | Collector's telemetry ingestion host. |
Backpressure emits stdout JSON with type: "telemetry_queue" and signal: "queue_dropped".
These signals contain operational queue identifiers and counters rather than product payloads.
See the MCP operations runbook.
MCP and asset serving
MCP is always mounted at {APP_BASE_URL}/mcp; there is no enable flag or separate port.
| Variable | Default | Purpose |
|---|---|---|
MCP_TELEMETRY_LOG | Enabled | Set false to suppress stdout mcp_telemetry logs. |
ASSET_PRELOAD_MAX_SIZE and ASSET_PRELOAD_VERBOSE_LOGGING are accepted by the environment
schema but are not consumed by the current API static-file serving implementation.
See MCP Server for OAuth scopes and client setup.
Example authenticated deployment
Use this as a configuration template, replacing every placeholder before starting:
NODE_ENV=production
APP_BASE_URL=https://your-domain.example
VITE_PUBLIC_APP_URL=https://your-domain.example
DURABULL_AUTHLESS=false
BETTER_AUTH_SECRET=<long-random-secret>
DATABASE_URL=postgresql://user:password@postgres.example.com:5432/durabull
DURABULL_REDIS_URL_ENCRYPTION_KEY=<64-character-hex-key>
DURABULL_ENV_CONNECTIONS=true
DURABULL_REDIS_URL_MAIN=rediss://user:password@redis.example.com:6379/0
DURABULL_REDIS_URL_MAIN_ENVIRONMENT=production
DURABULL_REDIS_URL_MAIN_PREFIX=bull
DURABULL_REDIS_URL_DEFAULT=MAINAdd DURABULL_SECRET_ENCRYPTION_KEY if you configure Linear or webhook signing. Review
Security and Hardening before publishing the app.