Obexal Docs

Docs/Self-hosting/Configuration

Configuration reference

The main environment variables of the auth-service, family by family: database, encryption, sessions, email, sign-in policies, storage and observability.

The auth-service follows the 12-factor model: all configuration comes from environment variables, loaded and validated at startup. This page lists the main variables by family, with their exact defaults.

How configuration is loaded

An invalid or missing required value stops the service at boot with an explicit error, never a silent fallback. Durations use the Go syntax (30m, 24h, 720h); booleans accept true and false. Two production guards are enforced: with APP_ENV=production, SESSION_SECURE must be true and MAIL_TRANSPORT=log is refused. SESSION_SECURE=true is also required whenever OIDC_ISSUER uses HTTPS.

Core service

VariableRoleDefault
APP_ENVdevelopment or production; production enables strict guardsdevelopment
HTTP_ADDRListen address of the API:8080
LOG_LEVELLevel of the JSON structured logsinfo
OIDC_ISSUERPublic URL of the API: the iss claim and the base of discovery URLshttp://localhost:8080
LOGIN_UI_URLPublic URL of the sign-in UI (magic links point to it)http://localhost:3000
ALLOWED_DATA_REGIONSData-residency regions allowed for tenants (CSV)eu

Database and Redis

VariableRoleDefault
DATABASE_URLPostgreSQL connection string; holds all durable staterequired
REDIS_URLRedis connection string; sessions and rate limiting, volatilerequired

On managed services, use sslmode=verify-full for PostgreSQL and rediss:// for Redis: TLS end to end.

Encryption at rest

VariableRoleDefault
ENCRYPTION_KEYPrimary AES-256-GCM key: encrypts TOTP secrets and the private OIDC signing keys stored in the database (base64, exactly 32 bytes)required
ENCRYPTION_KEY_OLDPrevious keys (CSV), kept for decryption only during a key rotationempty

Generate a key:

openssl rand -base64 32
Danger

Store ENCRYPTION_KEY in a secrets vault, separately from database backups. A restored dump is unreadable without the key that encrypted its secrets.

Sessions, cookies and proxies

VariableRoleDefault
SESSION_TTLSession lifetime24h
SESSION_SECUREMarks cookies Secure; mandatory in productionfalse
SESSION_COOKIE_NAMEName of the session cookieobexal_session
SESSION_COOKIE_DOMAINCookie domain, if shared across subdomainsempty
COOKIE_SAMESITElax, strict or nonelax
CSRF_COOKIE_NAMEName of the CSRF cookieobexal_csrf
ALLOWED_ORIGINSCORS origins allowed to call the API (CSV)empty
TRUSTED_PROXIESCIDR ranges of reverse proxies whose X-Forwarded-For is honoredempty
Warning

Leave TRUSTED_PROXIES empty and the service only trusts the TCP peer address: behind a proxy, all clients collapse onto the proxy IP and per-IP rate limiting stops working.

Token lifetimes

VariableRoleDefault
OAUTH_ACCESS_TOKEN_TTLAccess token lifetime10m
OAUTH_ID_TOKEN_TTLID token lifetime10m
OAUTH_REFRESH_TOKEN_TTLRefresh token lifetime720h
OAUTH_AUTH_CODE_TTLAuthorization code lifetime1m

These lifetimes also bound the grace period of a signing key rotation.

Email delivery

VariableRoleDefault
MAIL_TRANSPORTsmtp or log (debug: prints emails to the logs, refused in production)log
SMTP_HOSTSMTP relay host (choose an EU relay)empty
SMTP_PORTSMTP port587
SMTP_USERNAMESMTP userempty
SMTP_PASSWORDSMTP passwordempty
MAIL_FROMSender addressno-reply@obexal.local

Sign-in and account policies

VariableRoleDefault
REQUIRE_EMAIL_VERIFICATIONBlocks password sign-in for unverified email addressesfalse
EMAIL_OTPRequires an email code as second factor on password sign-in when the user has no TOTPtrue
MFA_ENROLLMENT_STRICTWhen a tenant requires MFA, rejects authenticated requests (403) until a factor is enrolledfalse
ORG_SIGNUP_ENABLEDAllows self-service organization creationtrue
ACCOUNT_SELF_DELETE_ENABLEDLets end users delete their own account (consumer tenants only)false
ACCOUNT_SELF_EMAIL_CHANGE_ENABLEDLets end users change their own email address (consumer tenants only)false

Rate limiting and lockout

VariableRoleDefault
RATE_LIMIT_LOGIN_MAXLogin attempts per account per window10
RATE_LIMIT_LOGIN_WINDOWLogin rate-limit window15m
RATE_LIMIT_LOGIN_IP_MAXLogin attempts per IP per window100
RATE_LIMIT_SIGNUP_MAXSign-ups per identifier per window5
RATE_LIMIT_SIGNUP_WINDOWSign-up rate-limit window1h
RATE_LIMIT_SIGNUP_IP_MAXSign-ups per IP per window50
LOGIN_LOCKOUT_MAXFailed attempts before locking an account (0 or less disables)10
LOGIN_LOCKOUT_WINDOWWindow counting the failures15m
LOGIN_LOCKOUT_DURATIONLock duration15m

Local data files

Two optional features read local files, with no network call and no data leaving your perimeter:

VariableRoleDefault
GEOIP_DB_PATHPath to a .mmdb GeoIP database for country rules in conditional accessempty
BREACHED_PASSWORD_FILEPath to a breached password corpus, HIBP SHA1:count format or plain textempty

Both fail open: if the file is missing or unreadable, the feature stays inert and nothing is blocked. Refresh the GeoIP file periodically (it is loaded at startup).

Object storage (tenant logos)

VariableRoleDefault
S3_ENDPOINTS3-compatible endpoint, host:port without schemeempty
S3_ACCESS_KEYAccess keyempty
S3_SECRET_KEYSecret keyempty
S3_BUCKETBucket for tenant branding assetsobexal-branding
S3_USE_SSLTLS towards the endpointfalse
S3_REGIONRegion label of the S3 protocolus-east-1

Logo upload is cleanly disabled unless endpoint, access key and secret key are all set. The default region label is only an S3 protocol convention used by MinIO: no US service is involved.

Webhooks and audit

VariableRoleDefault
WEBHOOK_WORKERSSize of the delivery worker pool4
WEBHOOK_QUEUE_SIZEDelivery queue capacity256
WEBHOOK_TIMEOUTTimeout of each delivery attempt10s
WEBHOOK_ALLOW_PRIVATE_TARGETSAllows webhook URLs pointing to private or loopback addressesfalse
AUDIT_RETENTIONRetention of the audit log; 0 disables purging0
Danger

WEBHOOK_ALLOW_PRIVATE_TARGETS=true is for development only. In production it opens the door to SSRF: a tenant admin could target your internal network. Keep it false.

AI agents

VariableRoleDefault
AGENT_AUTO_CONTAINMENT_ENABLEDAutomatically contains an AI agent whose activity spikes far beyond its baseline (applies the kill switch)true

Observability

VariableRoleDefault
METRICS_ENABLEDExposes GET /metrics in Prometheus formattrue
METRICS_TOKENIf set, requires Authorization: Bearer on /metricsempty
HTTP_REQUEST_TIMEOUTPer-request processing timeout (503 beyond it); 0 disables15s

Variables consumed by other components

These are not read by the auth-service:

  • OBEXAL_CONNECT_SRC: the connect-src CSP directive of the login and admin UIs. Tighten it to the exact API origin in production.
  • NEXT_PUBLIC_OBEXAL_API_URL, NEXT_PUBLIC_LOGIN_UI_URL, NEXT_PUBLIC_ADMIN_URL, NEXT_PUBLIC_ALLOWED_REDIRECTS: build arguments baked into the UI images.
  • OBEXAL_ACME_EMAIL, OBEXAL_API_HOST, OBEXAL_ADMIN_HOST, OBEXAL_LOGIN_HOST: consumed by the Caddy TLS overlay (see Deploy with Docker Compose).