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

Configuration Reference

Last Updated: 2026-04-25

Overview

Porta's configuration is managed through environment variables, validated at startup using a Zod schema (src/config/schema.ts). If any required variable is missing or invalid, the process exits immediately with a clear error message (fail-fast principle).

Configuration is loaded via src/config/index.ts, which reads from process.env (with .env file support via dotenv in development).

Environment Variables

Server

VariableTypeDefaultRequiredDescription
NODE_ENVdevelopment | test | productiondevelopmentNoRuntime environment mode
PORTInteger3000NoHTTP server listen port
HOSTString0.0.0.0NoHTTP server bind address
TRUST_PROXYBooleanfalseNoTrust X-Forwarded-* headers from reverse proxy
LOG_LEVELdebug | info | warn | error | fatalinfoNoPino log level

Database

VariableTypeDefaultRequiredDescription
DATABASE_URLString (URL)YesPostgreSQL connection string

Format: postgresql://user:password@host:port/database

Example: postgresql://porta:porta@localhost:5432/porta

Redis

VariableTypeDefaultRequiredDescription
REDIS_URLString (URL)YesRedis connection string

Format: redis://[password@]host:port[/db]

Example: redis://localhost:6379

OIDC

VariableTypeDefaultRequiredDescription
ISSUER_BASE_URLString (URL)YesBase URL for OIDC issuer. Must include protocol. Used to construct org-specific issuer URLs: {ISSUER_BASE_URL}/{orgSlug}
COOKIE_KEYSString (comma-separated)YesCookie signing keys for OIDC sessions. First key signs; subsequent keys verify only (supports key rotation). Each key must be ≥ 16 characters

COOKIE_KEYS format: Comma-separated list of secrets. For rotation, add a new key at the beginning:

bash
# Single key
COOKIE_KEYS=my-secret-key-at-least-16-chars

# Key rotation (new key first, old key still valid for verification)
COOKIE_KEYS=new-key-at-least-16-chars,old-key-still-valid

SMTP (Email)

VariableTypeDefaultRequiredDescription
SMTP_HOSTStringYesSMTP server hostname
SMTP_PORTInteger587NoSMTP server port
SMTP_USERStringNoSMTP authentication username
SMTP_PASSStringNoSMTP authentication password
SMTP_FROMStringYesSender email address for outgoing emails

Encryption Keys

VariableTypeDefaultRequiredDescription
SIGNING_KEY_ENCRYPTION_KEYString (64 hex chars)YesAES-256-GCM key for encrypting ES256 signing key private keys at rest. Must be exactly 64 hex characters (32 bytes)
TWO_FACTOR_ENCRYPTION_KEYString (64 hex chars)Prod: YesAES-256-GCM key for encrypting TOTP secrets. Must be exactly 64 hex characters (32 bytes). Optional in dev/test; required in production

Generate encryption keys:

bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# or
openssl rand -hex 32

Admin API

VariableTypeDefaultRequiredDescription
ADMIN_CORS_ORIGINSString (comma-separated URLs)"" (empty = deny all)NoAllowed CORS origins for /api/admin/*. Only needed for web admin dashboards on different origins

Monitoring

VariableTypeDefaultRequiredDescription
METRICS_ENABLEDBooleanfalseNoEnable Prometheus metrics at GET /metrics. Endpoint is unauthenticated — restrict access via network policy

Test Environment

These variables are used by the test suites (integration, e2e, pentest):

VariableTypeDefaultRequiredDescription
TEST_DATABASE_URLString (URL)For testsSeparate test database connection
TEST_REDIS_URLString (URL)For testsSeparate Redis DB index for test isolation
TEST_SMTP_HOSTStringFor testsTest SMTP host (MailHog)
TEST_SMTP_PORTIntegerFor testsTest SMTP port
TEST_MAILHOG_URLString (URL)For testsMailHog API URL for test assertions

Admin GUI (BFF)

These variables configure the Admin GUI BFF server (admin-gui/). They are separate from the main Porta server configuration.

VariableTypeDefaultRequiredDescription
PORTA_SERVICEadminYes (Docker)Set to admin to start the BFF instead of the OIDC server
PORTA_ADMIN_PORTA_URLString (URL)YesInternal URL of the Porta server (e.g., http://porta:3000 in Docker, http://localhost:3000 in dev)
PORTA_ADMIN_CLIENT_IDStringYesOIDC client ID for the GUI confidential client (from porta init output)
PORTA_ADMIN_CLIENT_SECRETStringYesOIDC client secret for the GUI confidential client
PORTA_ADMIN_SESSION_SECRETStringYesSession encryption key (minimum 32 characters)
PORTA_ADMIN_PORTInteger4002NoBFF listen port
PORTA_ADMIN_PUBLIC_URLString (URL)http://localhost:4002NoPublic URL for OIDC redirect URIs
PORTA_ADMIN_ORG_SLUGStringAuto-detectedNoSuper-admin org slug (auto-detected from Porta metadata if not set)
REDIS_URLString (URL)YesRedis URL for session storage (use DB 1: redis://localhost:6379/1)
NODE_ENVStringdevelopmentNoRuntime environment
LOG_LEVELStringinfoNoPino log level

Session storage: The BFF uses Redis DB index 1 (separate from Porta's DB index 0) for session persistence. Sessions are server-side only — the browser receives an opaque session cookie.

Internal / Escape Hatch

VariableTypeDefaultRequiredDescription
PORTA_SKIP_PROD_SAFETYBooleanfalseNoEmergency only: Skip production safety checks. Logs an ERROR when used. For incident response only — never set in normal operation

Production Safety Checks

When NODE_ENV=production, Porta enforces additional validation rules via Zod's superRefine. These prevent deploying with development placeholder values:

RuleCheckError
R1COOKIE_KEYS contains no change-me patternsRejects dev placeholders
R2Each cookie key ≥ 32 charactersEnsures sufficient entropy
R3TWO_FACTOR_ENCRYPTION_KEY is presentRequired for 2FA in production
R4TWO_FACTOR_ENCRYPTION_KEY ≠ dev placeholderRejects 0123456789abcdef...
R5SIGNING_KEY_ENCRYPTION_KEY ≠ dev placeholderRejects fedcba9876543210...
R6DATABASE_URL doesn't contain porta_dev passwordRejects dev credentials
R7ISSUER_BASE_URL uses HTTPS (unless localhost)Enforces TLS in production
R8LOG_LEVEL is not debugPrevents verbose logging
R9SMTP_HOST is not localhost/127.x.x.xRejects dev MailHog

System Config (Runtime)

In addition to environment variables, Porta reads runtime configuration from the system_config PostgreSQL table. These values are cached in-memory for 60 seconds (src/lib/system-config.ts).

System config is managed via:

  • CLI: porta config list/get/set
  • API: GET/PUT /api/admin/config

System Config Keys

KeyTypeDescription
oidc.ttl.accessTokenNumber (seconds)Access token TTL
oidc.ttl.refreshTokenNumber (seconds)Refresh token TTL
oidc.ttl.idTokenNumber (seconds)ID token TTL
oidc.ttl.sessionNumber (seconds)OIDC session TTL
oidc.ttl.interactionNumber (seconds)Interaction TTL
oidc.ttl.authorizationCodeNumber (seconds)Authorization code TTL
oidc.ttl.grantNumber (seconds)Grant TTL

These TTLs are loaded at startup and passed to the OIDC provider configuration.

Example .env File

bash
# Server
NODE_ENV=development
PORT=3000
HOST=0.0.0.0

# Database
DATABASE_URL=postgresql://porta:porta_dev@localhost:5432/porta

# Redis
REDIS_URL=redis://localhost:6379

# OIDC
ISSUER_BASE_URL=http://localhost:3000
COOKIE_KEYS=dev-cookie-key-change-me-in-production

# Email (MailHog for dev)
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_USER=
SMTP_PASS=
SMTP_FROM=noreply@porta.local

# Logging
LOG_LEVEL=debug

# Reverse proxy
TRUST_PROXY=false

# Encryption keys (dev placeholders — replace in production!)
TWO_FACTOR_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
SIGNING_KEY_ENCRYPTION_KEY=fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210

# Metrics (disabled by default)
METRICS_ENABLED=false

Config Loading Flow

  1. dotenv loads .env file (if present)
  2. Environment variables are mapped to the Zod schema field names
  3. Zod validates types, formats, and defaults
  4. In production, superRefine runs safety checks
  5. Valid config is frozen and exported as a singleton
  6. Invalid config triggers immediate process exit

Released under the MIT License.