Setup
Configure the gateway: requirements, environment, secrets, and choosing a database and Redis.
Everything the gateway needs before you deploy. To just see it running, the Quickstart is faster; come here to configure a real environment, then pick a target under Deployment.
Requirements
- Bun 1.3+ — the gateway runtime (runs TypeScript directly; no build step) and the package manager / task runner.
- Postgres 18+
- Redis 8+
Bifrost runs on Bun, not Node. If you plan to reach a database or Redis over TLS with a self-signed certificate, read Troubleshooting first — Bun's TLS may not accept those, and the fix is a configuration choice you make here.
Environment
Create apps/gateway/.env (copy apps/gateway/.env.example). The minimum:
PORT=4000
NODE_ENV=production
MASTER_KEY=replace-with-at-least-32-random-characters
ENCRYPTION_KEYRING={"primary":"64_hex_chars_32_bytes"}
ACTIVE_ENCRYPTION_KEY_ID=primary
DATABASE_URL=postgres://user:pass@host:5432/bifrost
REDIS_URL=redis://host:6379Everything else ships with production-ready defaults — override only what you need. The most common:
| Variable | Default | Purpose |
|---|---|---|
SHUTDOWN_TIMEOUT_MS | 10000 | Drain budget on SIGTERM/SIGINT. |
TRUSTED_PROXY_HOPS | 0 | Trusted rightmost proxy hops used to resolve the client IP. |
OTEL_ENABLED | false | Set with OTEL_EXPORTER_OTLP_ENDPOINT to export traces/metrics. |
BIFROST_EXTENSIONS_RELOAD_INTERVAL_MS | 15000 | How often each replica polls for extension changes to hot-reload. |
BIFROST_EXTENSIONS_MAX_CODE_BYTES | 1000000 | Maximum size of an uploaded extension module (bytes). |
Full list of every variable, including OpenTelemetry and response-state retention: Environment variables.
Secrets
Store the root credential and encryption keyring in your secret manager — never in git or the image:
| Secret | Purpose | Format |
|---|---|---|
MASTER_KEY | Operator credential; full access to /admin/*. | Strong random string, at least 32 characters. |
ENCRYPTION_KEYRING | Encrypts credentials, extension source, compaction capsules, and forensic samples. | JSON key-id to 64-hex-key map. |
ACTIVE_ENCRYPTION_KEY_ID | Selects the key used for new envelopes. | An id present in the keyring. |
openssl rand -base64 48 # MASTER_KEY
openssl rand -hex 32 # one ENCRYPTION_KEYRING valueRotation procedures live in Operations → Secrets.
Database and Redis
The gateway needs a Postgres 18+ database and a Redis 8+ instance. How you connect matters because of the Bun TLS constraint:
- Self-hosted on the same private network (Compose / Coolify / Portainer / Dokploy): connect over
plaintext —
postgres://…andredis://…. Safe by network isolation, and it sidesteps the self-signed TLS issue. This is the default in every Deployment recipe. - Managed provider (recommended for development, or when the database lives off-network): pick one that presents a public-CA certificate, which Bun connects to cleanly.
Managed database and Redis
Good free-tier options that work with Bun's TLS out of the box:
| Service | Type | Notes |
|---|---|---|
| Neon | Postgres | Serverless, generous free tier, public-CA TLS, connect by hostname. |
| Supabase | Postgres | Free tier; use the connection string or the pooler. |
| Aiven | Postgres / Redis | Free tier; public-CA TLS. |
| Upstash | Redis | Free tier; rediss:// over public-CA TLS. |
Avoid pointing the gateway at a self-signed database over a public port (the default for a raw Coolify/Dokploy database exposed publicly) — see Troubleshooting.