⚠️ Porta is in beta — APIs and features may change before v1.0
Skip to content

Environment Variables

Complete reference for all environment variables used to configure Porta.

See also: Quick Start for minimal setup, Deployment Guide for production guidance.

Server

VariableDefaultRequiredDescription
NODE_ENVdevelopmentNoRuntime mode (development, production, test). Controls log format, cookie defaults, and other behavior.
PORT3000NoHTTP listen port.
HOST0.0.0.0NoHTTP listen address. Use 127.0.0.1 to restrict to localhost.

Database & Cache

VariableDefaultRequiredDescription
DATABASE_URLYesPostgreSQL connection string. Example: postgresql://porta:secret@localhost:5432/porta
REDIS_URLYesRedis connection string. Example: redis://localhost:6379

OIDC

VariableDefaultRequiredDescription
ISSUER_BASE_URLYesThe public-facing URL of your Porta instance. Must match the URL users see in their browser (e.g., https://auth.example.com). OIDC tokens embed this as the iss claim — clients validate it, so it must be correct.
COOKIE_KEYSYesCookie signing key(s). Must be at least 32 random characters. For key rotation, use comma-separated values with the newest key first (e.g., new-key,old-key). See Cookie Key Rotation.

Email (SMTP)

VariableDefaultRequiredDescription
SMTP_HOSTYes (prod)SMTP relay hostname. Use localhost with MailHog for development.
SMTP_PORT587NoSMTP port. Common values: 587 (STARTTLS), 465 (implicit TLS), 25 (unencrypted), 1025 (MailHog).
SMTP_USERNoSMTP authentication username. Leave empty for MailHog.
SMTP_PASSNoSMTP authentication password. Leave empty for MailHog.
SMTP_FROMnoreply@porta.localNoSender email address for magic links, password resets, and invitations.

Monitoring

VariableDefaultRequiredDescription
METRICS_ENABLEDfalseNoSet to true to enable the Prometheus-compatible GET /metrics endpoint. When disabled (default), the endpoint returns 404.

Logging

VariableDefaultRequiredDescription
LOG_LEVELinfo (prod), debug (dev)NoLog verbosity. Values: debug, info, warn, error, silent.

Porta uses pino for structured logging:

NODE_ENVFormatBehavior
developmentPretty-printed (pino-pretty)Human-readable, colorized
productionJSON (one line per entry)Machine-parseable for log aggregators
testSilentNo log output

Reverse Proxy

VariableDefaultRequiredDescription
TRUST_PROXYfalseYes (behind proxy)Set to true when Porta runs behind a TLS-terminating reverse proxy (nginx, Traefik, Caddy, cloud load balancer, etc.).

Why TRUST_PROXY Matters

Porta sets the Secure flag on authentication cookies based on the actual connection protocol (ctx.secure in Koa). In a typical production setup, a reverse proxy terminates TLS and forwards requests to Porta over plain HTTP:

Browser ──HTTPS──▶ Reverse Proxy ──HTTP──▶ Porta (port 3000)

Without TRUST_PROXY=true, Porta sees only the internal HTTP connection and sets cookies without the Secure flag. Modern browsers then silently drop these cookies on HTTPS pages, causing OIDC login flows to fail — the interaction session is lost between redirects.

When TRUST_PROXY=true, Koa reads the X-Forwarded-Proto header from the proxy to determine the original protocol. This makes ctx.secure return true when the browser connected via HTTPS, so cookies are correctly flagged as Secure.

Affected features:

  • CSRF tokens (login forms)
  • OIDC interaction sessions (login/consent)
  • Magic link sessions

Do Not Enable Without a Proxy

Only set TRUST_PROXY=true when Porta is actually behind a trusted reverse proxy. Enabling it without a proxy allows clients to spoof X-Forwarded-* headers.

Common Scenarios

SetupTRUST_PROXYNotes
Direct HTTP (dev/eval)falseDefault — cookies use Secure: false
Behind nginx/Traefik/Caddy with TLStrueProxy must send X-Forwarded-Proto: https
Behind a cloud load balancer (AWS ALB, GCP LB)trueCloud LBs typically set X-Forwarded-Proto
Direct HTTPS (TLS on Porta itself)falsePorta sees TLS directly — no proxy headers needed

Security

VariableDefaultRequiredDescription
TWO_FACTOR_ENCRYPTION_KEYYes (prod)AES-256-GCM key for encrypting TOTP secrets. Must be exactly 64 hex characters (32 bytes). Optional in development/test.
SIGNING_KEY_ENCRYPTION_KEYYesAES-256-GCM key for encrypting ES256 signing key private keys at rest. Must be exactly 64 hex characters (32 bytes). Always required — Porta will not start without it.
PORTA_SKIP_PROD_SAFETYfalseNoEmergency escape hatch to bypass production config safety checks. When true, Porta logs an ERROR instead of exiting on startup. Do not use in normal production — this is intended only for disaster recovery or migration scenarios. See Production Safety Checks.

Production Safety Checks

When NODE_ENV=production, Porta validates your configuration at startup and exits with a clear error if any safety rule fails. This prevents accidental deployment with development-only placeholder values.

RuleWhat It Checks
R1COOKIE_KEYS does not contain a dev placeholder ("change-me" pattern)
R2COOKIE_KEYS is at least 32 characters
R3TWO_FACTOR_ENCRYPTION_KEY is set (required in production)
R4TWO_FACTOR_ENCRYPTION_KEY is not the development placeholder (0123456789abcdef…)
R5SIGNING_KEY_ENCRYPTION_KEY is not the development placeholder (fedcba9876543210…)
R6DATABASE_URL does not contain the dev password (porta_dev)
R7ISSUER_BASE_URL uses https:// for non-localhost hosts
R8LOG_LEVEL is not debug (prevents verbose logging in production)
R9SMTP_HOST is not localhost / 127.x.x.x (catches MailHog dev inbox)

If you need to temporarily bypass these checks (e.g., during disaster recovery), set PORTA_SKIP_PROD_SAFETY=true. Porta will still log each violation as an ERROR but will not exit.

DANGER

PORTA_SKIP_PROD_SAFETY=true should never be used in normal production. It exists only for emergency situations where you need to start Porta with an incomplete configuration.

Generating Secrets

bash
# Cookie signing key (random 64-char string)
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"

# Two-factor encryption key (64 hex chars)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Signing key encryption key (64 hex chars)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Database password
node -e "console.log(require('crypto').randomBytes(24).toString('base64url'))"

Startup Behavior

VariableDefaultRequiredDescription
PORTA_AUTO_MIGRATEfalseNoWhen true, the Docker entrypoint runs database migrations automatically before starting the server. Convenient for initial setup; disable in production after the schema is stable.
PORTA_WAIT_TIMEOUT60NoMaximum seconds the Docker entrypoint waits for PostgreSQL and Redis to become available before exiting.

Test Environment

These variables are used by the test suite and should not be set in production.

VariableDefaultDescription
TEST_DATABASE_URLPostgreSQL connection string for the test database, keeping test data isolated from development data.
TEST_REDIS_URLRedis connection string (typically a different DB index) for test isolation.

Docker Service Mode

VariableDefaultRequiredDescription
PORTA_SERVICEserverNoWhich service to run: server (OIDC server) or admin (Admin GUI BFF). Used in Docker deployments.

Admin GUI

These variables are required when running the Admin GUI BFF (PORTA_SERVICE=admin). See Admin GUI Guide for full setup instructions.

VariableDefaultRequiredDescription
PORTA_ADMIN_PORT4002NoPort for the admin GUI BFF server.
PORTA_ADMIN_PORTA_URLYesURL of the Porta OIDC server (e.g., http://localhost:3000).
PORTA_ADMIN_CLIENT_IDYesOIDC client ID for the admin GUI (created by porta init).
PORTA_ADMIN_CLIENT_SECRETYesOIDC client secret for the admin GUI (created by porta init).
PORTA_ADMIN_SESSION_SECRETYesSecret for signing session cookies (min 32 characters).
PORTA_ADMIN_PUBLIC_URLhttp://localhost:4002NoPublic-facing URL of the admin GUI.
PORTA_ADMIN_ORG_SLUGAuto-detectedNoOrganization slug for OIDC discovery.
PORTA_ADMIN_SESSION_TTL3600NoSession duration in seconds.

Example .env Files

Porta ships with two example files:

  • .env.example — Development defaults (local PostgreSQL, Redis, MailHog)
  • .env.docker — Docker Compose defaults (service hostnames, production mode)

Copy the appropriate file and customize:

bash
# For local development
cp .env.example .env

# For Docker Compose
cp .env.docker .env.docker.local

Released under the MIT License.