Environment Variables Reference
Complete reference for all MPG_ configuration variables for both the Admin Backend and Main Backend.
Environment Variables Reference
All configuration uses the MPG_ prefix, loaded by Viper from environment variables or a .env file.
[!NOTE] Both backends share many variable names (database, cache, logging, OTEL, rate limiting, encryption). Where the variable name is the same, it applies identically to both services unless noted.
Shared Variables (Both Backends)
Server
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_ENV | string | No | production | Runtime environment: dev, production, production-cloud |
Database (MongoDB)
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_DATABASE_URI | string | Yes | — | MongoDB connection string. Bundled MongoDB uses mongodb://user:pass@mongo:27017/database?authSource=database&replicaSet=rs0; customer-supplied Atlas URIs remain unchanged. |
MPG_DATABASE_NAME | string | Yes | — | MongoDB database name |
MPG_DATABASE_MAX_POOL_SIZE | int | No | 100 | Maximum connection pool size |
MPG_DATABASE_MIN_POOL_SIZE | int | No | 10 | Minimum connection pool size |
MPG_DATABASE_MAX_CONN_IDLE_TIME | duration | No | 30m | Maximum time a connection can be idle |
MPG_DATABASE_MAX_CONNECTING | int | No | 10 | Maximum concurrent connection attempts |
MPG_DATABASE_CONNECT_TIMEOUT | duration | No | 10s | Connection establishment timeout |
Cache (Redis / Garnet)
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_GARNET_URL | string | No | — | Redis-compatible cache URL (e.g., redis://localhost:6379). If unset, in-memory cache is used. |
Logging
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_LOG_LEVEL | string | No | error | Log level: debug, info, warn, error, fatal, panic |
MPG_LOG_FORMAT | string | No | json | Log format: json (structured) or text |
OpenTelemetry (Tracing)
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_OTEL_ENABLED | bool | No | false | Enable OpenTelemetry tracing |
MPG_OTEL_EXPORTER_OTLP_PROTOCOL | string | No | — | OTLP protocol: grpc or http/protobuf |
MPG_OTEL_EXPORTER_OTLP_ENDPOINT | string | No | — | OTLP collector endpoint URL |
MPG_OTEL_EXPORTER_OTLP_HEADERS | string | No | — | OTLP authentication headers (comma-separated key=value) |
MPG_OTEL_RESOURCE_ATTRIBUTES | string | No | — | Resource attributes (e.g., service.name=payment-gateway) |
MPG_OTEL_EXPORTER_OTLP_INSECURE | bool | No | false | Skip TLS verification for OTLP endpoint |
Rate Limiting
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_RATE_LIMIT_ENABLED | bool | No | true | Enable request rate limiting |
MPG_RATE_LIMIT_WINDOW_SIZE | duration | No | 5m | Request window size |
MPG_RATE_LIMIT_MAX_REQUESTS | int | No | 500 | Maximum requests per window |
MPG_RATE_LIMIT_REQUESTS_PER_MIN | int | No | 100 | Maximum requests per minute |
MPG_RATE_LIMIT_WHITELIST | string | No | 127.0.0.1,::1 | Comma-separated IPs to exempt from rate limiting |
In v6.0.0, POST /api/v1/auth/refresh-token and GET /api/v1/auth/login/check are excluded from the ordinary Admin API request budget. Each has its own per-IP fixed-window counter. Refresh allows 20 requests per 10 minutes; login checks use MPG_RATE_LIMIT_MAX_REQUESTS and MPG_RATE_LIMIT_WINDOW_SIZE (defaults: 500 requests per 5 minutes). Exhausted counters return 429 with Retry-After; an unavailable rate-limit store returns 503 with Retry-After: 1.
MPG_RATE_LIMIT_ENABLED controls whether these authentication limits are active. The refresh maximum/window are fixed, and neither authentication budget uses MPG_RATE_LIMIT_WHITELIST. There is no shared deployment-wide refresh budget. Only the explicit refresh endpoint rotates refresh credentials; see session recovery.
Security & Network Trust
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_SECURITY_TRUSTED_PROXIES | string | No | internal container ranges | Comma-separated CIDRs/IPs of trusted reverse proxies. Client-IP forwarding headers (X-Real-IP, X-Forwarded-For) are honoured only when the immediate peer matches one of these entries; otherwise the raw connection IP is used for rate limiting and session IP binding. Provider-agnostic — does not require Cloudflare. Set to your load balancer's CIDR(s) if you front the stack with an external proxy. Both backends. |
MPG_INTERNAL_HEALTH_TOKEN | string | No | — (source-IP check only) | Shared secret required, in addition to the private/loopback source check, for the /internal/health deep endpoint. Behind a proxy the connection IP is the proxy, so this token is the real access gate. Set in production. Both backends. |
MPG_IPN_ALLOW_PRIVATE_TARGETS | bool | No | false | Allow IPN webhook delivery to private/loopback/link-local targets (SSRF guard). Keep false in production. Main backend only. |
MPG_SECURITY_ALLOW_PRIVATE_SMTP | bool | No | false | Allow SMTP test/send to dial private/loopback/link-local hosts (SSRF guard; cloud-metadata endpoints stay blocked regardless). Keep false in production. Admin backend only. |
Note: The bundled Caddy reverse proxy forwards an authoritative
X-Real-IPderived from its own trusted-proxy configuration, so the backends only need to trust the proxy hop (MPG_SECURITY_TRUSTED_PROXIESdefaults to the internal container networks). Cloudflare is not required — any reverse proxy, or no proxy at all, is supported.
Encryption
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_SYSTEM_ENCRYPTION_KEY | string | Yes | — | Hex-encoded symmetric key for encrypting KMS credentials. Admin backend requires exactly 32 bytes (64 hex characters). Main backend accepts 32+ bytes, but use 32 bytes to keep environments consistent. |
MPG_SYSTEM_SEARCH_HASH_KEY | string | Yes | — | Hex-encoded HMAC key for deterministic searchable encryption. Exactly 32 bytes (64 hex characters). |
Admin Backend Variables
Server
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_ADMIN_BACKEND_HOST | string | Yes | — | Bind address (e.g., 0.0.0.0) |
MPG_ADMIN_BACKEND_PORT | int | Yes | — | HTTP port (e.g., 8080) |
MPG_ADMIN_BACKEND_HTTPS | bool | No | false | Enable TLS termination at the backend |
MPG_ADMIN_BACKEND_HTTPS_CERT | string | No | — | Path to TLS certificate file |
MPG_ADMIN_BACKEND_HTTPS_KEY | string | No | — | Path to TLS private key file |
MPG_ADMIN_BACKEND_DOMAIN | string | No | — | Public domain of the admin backend (optional; used for logging/metadata, not required by startup validation) |
MPG_ADMIN_FRONTEND_DOMAIN | string | Yes | — | Admin frontend domain for CORS allow-list (e.g., admin.yourcompany.com) |
MPG_MAIN_BACKEND_DOMAIN | string | Yes | — | Main backend public domain |
MPG_MAIN_FRONTEND_DOMAIN | string | Yes | — | Main frontend public domain |
MPG_MAIN_FRONTEND_SERVICE | string | Yes | — | Deployment-managed service hostname for the main frontend |
MPG_MAIN_FRONTEND_PORT | string | Yes | — | Deployment-managed service port for the main frontend |
MPG_MAIN_BACKEND_SERVICE | string | Yes | — | Deployment-managed service hostname for the main backend |
MPG_MAIN_BACKEND_PORT | string | Yes | — | Deployment-managed service port for the main backend |
Authentication
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_SYSTEM_REFRESH_KEY | string | Yes | — | Secret key for signing JWT refresh tokens (hex-encoded, exactly 64 bytes / 128 hex characters) |
MPG_COOKIE_AUTH_KEY | string | Yes | — | Session cookie authentication key (hex-encoded, 64 bytes recommended) |
MPG_COOKIE_ENCRYPTION_KEY | string | Yes | — | Session cookie encryption key (hex-encoded, 32 bytes) |
MPG_WEBAUTHN_RPDISPLAYNAME | string | No | — | Display name shown in passkey dialogs (e.g., My Company Admin) |
MPG_WEBAUTHN_DEBUG | bool | No | false | Enable verbose WebAuthn debug logging |
External Services
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_MAIN_WORKER_SERVICE_URL | string | No | — | Internal URL of the worker service for PDF proxy requests |
MPG_LICENSING_AUTHORITY_URL | string | No | — | Trusted vendor licensing endpoint. Leave unset for official deployments unless support instructs otherwise. |
Main Backend Variables
Server
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_MAIN_BACKEND_HOST | string | Yes | — | Bind address (e.g., 0.0.0.0) |
MPG_MAIN_BACKEND_PORT | int | Yes | — | HTTP port (e.g., 8081) |
MPG_MAIN_BACKEND_HTTPS | bool | No | false | Enable TLS at backend |
MPG_MAIN_BACKEND_HTTPS_CERT | string | No | — | TLS certificate path |
MPG_MAIN_BACKEND_HTTPS_KEY | string | No | — | TLS private key path |
MPG_MAIN_BACKEND_DOMAIN | string | Yes | — | Public domain for this backend |
MPG_MAIN_FRONTEND_DOMAIN | string | Yes | — | Main frontend domain for CORS |
Worker (PDF Generation)
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
MPG_MAIN_WORKER_GOTENBERG_URL | string | No | http://localhost:3000 | URL of the Gotenberg PDF service; deployment templates set this to the internal Gotenberg service. |
MPG_MAIN_WORKER_TEMP_CACHE_DIR | string | No | OS temp dir + /pdf-cache | Local directory for temporary PDF caching (defaults to the host OS temp directory). In container deployments this is commonly set explicitly (e.g. /tmp/pdf-cache). |
MPG_MAIN_WORKER_SERVICE_URL | string | No | — | Internal URL where the worker HTTP server is reachable (used by the main API to proxy PDF requests) |
MPG_MAIN_WORKER_HOST | string | No | 0.0.0.0 | Worker HTTP server bind address |
MPG_MAIN_WORKER_PORT | int | No | 8090 | Worker HTTP server port |
MPG_MAIN_WORKER_CONCURRENCY | int | No | 10 | Maximum concurrent PDF jobs |
MPG_MAIN_WORKER_SHUTDOWN_TIMEOUT | int | No | 10 | Graceful shutdown timeout in seconds |
Generating Secure Keys
Use openssl to generate cryptographically secure keys:
# 32-byte key (64 hex chars) — for SYSTEM_ENCRYPTION_KEY, SYSTEM_SEARCH_HASH_KEY, COOKIE_ENCRYPTION_KEY
openssl rand -hex 32
# 64-byte key (128 hex chars) — for COOKIE_AUTH_KEY, SYSTEM_REFRESH_KEY
openssl rand -hex 64[!IMPORTANT] Generate unique keys for each environment (development, staging, production). Never reuse keys across environments. Rotate keys if they are ever exposed.