Deployment

Environment Variables

Complete reference for all production environment variables.

Environment Variables

This reference lists environment variables used by the production Docker Compose variants.

Each variant has a committed example env file in deployment/env/: deployment/env/.env.prod.example, deployment/env/.env.prod.local.example, deployment/env/.env.prod.external-keycloak.example, and deployment/env/.env.prod.traefik.example.

Deployment Variant Summary

Compose FilePurposeNotes
compose.prod.yamlDefault production (no Traefik, bundled Keycloak)Direct host ports (3000, 8080, 8090), localhost-bound by default
compose.prod.external-keycloak.yamlProduction with external Keycloak (no Traefik)Requires explicit Keycloak URLs/realm envs, localhost-bound ports by default
compose.prod.traefik.yamlAdvanced/secondary production (Traefik + LetsEncrypt)Requires DNS and TLS-related envs
compose.prod.local.yamlProduction-like local stackUses local defaults and *.localhost

BFF Exposure Model

LAREX frontend runs a Nuxt BFF layer. Browser traffic is expected to hit the frontend service (/api/* on the same origin), while the frontend talks to backend via NUXT_API_BASE_INTERNAL.

Direct public backend exposure is deployment-specific (for example debugging/legacy API routing), not required for normal frontend operation.

Shared Production Variables

PostgreSQL

VariableDefaultDescription
POSTGRES_USER-Database username (required)
POSTGRES_PASSWORD-Database password (required)
POSTGRES_DBlarexdbDatabase name
LAREX_PUBLISH_IP127.0.0.1 (no-Traefik presets)Host interface for published frontend/app/Keycloak ports
LAREX_LOCAL_BIND_IP127.0.0.1 (local preset)Host interface for local Traefik and Mailpit ports

Application / Backend

VariableDefaultDescription
CORS_ALLOWED_ORIGIN-Allowed frontend origin (required for production variants)
KEYCLOAK_ADMIN_CLIENT_SECRET-Backend service client secret (required)
KEYCLOAK_RESOURCE_CLIENT_IDlarex-backend (bundled presets)Backend resource client ID
MAIL_ENABLEDtrueEnable email functionality
MAIL_HOSTsmtp.example.comSMTP server hostname
MAIL_PORT587SMTP port
MAIL_USERNAME-SMTP username
MAIL_PASSWORD-SMTP password
MAIL_FROMnoreply@example.comSender address
MAIL_SMTP_AUTHtrueEnable SMTP authentication
MAIL_SMTP_STARTTLStrueEnable STARTTLS

Bundled Keycloak Variables

Used by compose.prod.yaml, compose.prod.traefik.yaml, and compose.prod.local.yaml.

VariableDefaultDescription
KEYCLOAK_ADMIN-Keycloak bootstrap admin username
KEYCLOAK_ADMIN_PASSWORD-Keycloak bootstrap admin password
KEYCLOAK_HOSTNAMEVariant-specificPublic Keycloak hostname (or localhost:8090 in default no-Traefik preset)
KEYCLOAK_ADMIN_SERVER_URLhttp://keycloak:8080 (bundled presets)Backend admin client URL override (internal service URL)
KEYCLOAK_ADMIN_REALMlarex-prod (prod presets), larex-dev (local preset)Realm used by backend admin client

External Keycloak Variables

Required for compose.prod.external-keycloak.yaml.

VariableDefaultDescription
KEYCLOAK_ADMIN_SERVER_URL-External Keycloak admin base URL
KEYCLOAK_ADMIN_REALM-Realm used by the backend admin client
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI-JWT issuer URI used by Spring Security
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URIComputed by Spring (optional)Optional override for JWK endpoint

Traefik-Only Variables (Advanced/Secondary Preset)

Used by compose.prod.traefik.yaml.

VariableDefaultDescription
ACME_EMAIL-Email used by LetsEncrypt/ACME
FRONTEND_HOSTNAME-Public frontend hostname used by Traefik routers
API_HOSTNAME-Public API hostname used by Traefik app router (only needed when exposing backend directly)
KEYCLOAK_HOSTNAME-Public Keycloak hostname used by Traefik routers
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI-Public Keycloak issuer URI (recommended explicit setting)
NUXT_OAUTH_KEYCLOAK_SERVER_URL-Public Keycloak URL for frontend OAuth flows
NUXT_OAUTH_KEYCLOAK_REDIRECT_URL-OAuth redirect URL for frontend

Frontend Runtime OAuth Variables

These are used by production compose variants to configure Nuxt runtime auth settings.

VariableDefaultDescription
NUXT_SESSION_PASSWORD-Session encryption secret for nuxt-auth-utils (required, 32+ chars)
NUXT_API_BASE_INTERNALhttp://app:8080/api/v1Internal backend URL used by the frontend container
NUXT_OAUTH_KEYCLOAK_SERVER_URLVariant-specificPublic Keycloak URL used by the browser
NUXT_OAUTH_KEYCLOAK_SERVER_URL_INTERNALVariant-specificInternal Keycloak URL used by server-side token refresh/logout
NUXT_OAUTH_KEYCLOAK_REALMVariant-specificKeycloak realm name
NUXT_OAUTH_KEYCLOAK_CLIENT_IDVariant-specificFrontend OAuth client ID
NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET-Frontend OAuth client secret
NUXT_OAUTH_KEYCLOAK_REDIRECT_URLVariant-specificOAuth callback URL

Backend / Spring Override Variables

These can be used to override values from application-prod.yaml without editing code.

VariableDefaultDescription
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URIProfile config / compose overrideJWT issuer URI expected by backend
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URIDerived from issuer (unless overridden)JWK endpoint override (useful with internal Keycloak network URL)
KEYCLOAK_ADMIN_SERVER_URLProfile config / compose overrideKeycloak admin API URL
KEYCLOAK_ADMIN_REALMProfile config / compose overrideKeycloak admin realm
KEYCLOAK_RESOURCE_CLIENT_IDProfile config / compose overrideBackend resource client ID

Variant Examples

The examples below are also available as ready-to-copy files in deployment/env/.

Example: Default Production (compose.prod.yaml)

POSTGRES_USER=larex_prod
POSTGRES_PASSWORD=your-secure-password
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=your-admin-password
KEYCLOAK_ADMIN_CLIENT_SECRET=your-backend-client-secret
KEYCLOAK_RESOURCE_CLIENT_ID=larex-backend
CORS_ALLOWED_ORIGIN=http://localhost:3000

NUXT_SESSION_PASSWORD=replace-with-random-32-plus-character-secret
NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET=your-frontend-client-secret
NUXT_OAUTH_KEYCLOAK_SERVER_URL=http://localhost:8090
NUXT_OAUTH_KEYCLOAK_SERVER_URL_INTERNAL=http://keycloak:8080
NUXT_OAUTH_KEYCLOAK_REALM=larex-prod
NUXT_OAUTH_KEYCLOAK_CLIENT_ID=larex-frontend
NUXT_OAUTH_KEYCLOAK_REDIRECT_URL=http://localhost:3000/auth/keycloak

SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=http://localhost:8090/realms/larex-prod
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI=http://keycloak:8080/realms/larex-prod/protocol/openid-connect/certs

Example: External Keycloak (compose.prod.external-keycloak.yaml)

POSTGRES_USER=larex_prod
POSTGRES_PASSWORD=your-secure-password
CORS_ALLOWED_ORIGIN=https://app.example.org

KEYCLOAK_RESOURCE_CLIENT_ID=larex-backend
KEYCLOAK_ADMIN_CLIENT_SECRET=your-backend-client-secret
KEYCLOAK_ADMIN_SERVER_URL=https://auth.example.org
KEYCLOAK_ADMIN_REALM=larex-prod
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=https://auth.example.org/realms/larex-prod

NUXT_SESSION_PASSWORD=replace-with-random-32-plus-character-secret
NUXT_OAUTH_KEYCLOAK_SERVER_URL=https://auth.example.org
NUXT_OAUTH_KEYCLOAK_SERVER_URL_INTERNAL=https://auth.example.org
NUXT_OAUTH_KEYCLOAK_REALM=larex-prod
NUXT_OAUTH_KEYCLOAK_CLIENT_ID=larex-frontend
NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET=your-frontend-client-secret
NUXT_OAUTH_KEYCLOAK_REDIRECT_URL=https://app.example.org/auth/keycloak

Example: Advanced/Secondary Traefik (compose.prod.traefik.yaml)

POSTGRES_USER=larex_prod
POSTGRES_PASSWORD=your-secure-password
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=your-admin-password
KEYCLOAK_ADMIN_CLIENT_SECRET=your-backend-client-secret
KEYCLOAK_RESOURCE_CLIENT_ID=larex-backend

FRONTEND_HOSTNAME=app.example.org
API_HOSTNAME=api.example.org
KEYCLOAK_HOSTNAME=auth.example.org
CORS_ALLOWED_ORIGIN=https://app.example.org
ACME_EMAIL=admin@example.org

SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=https://auth.example.org/realms/larex-prod
NUXT_SESSION_PASSWORD=replace-with-random-32-plus-character-secret
NUXT_OAUTH_KEYCLOAK_SERVER_URL=https://auth.example.org
NUXT_OAUTH_KEYCLOAK_SERVER_URL_INTERNAL=http://keycloak:8080
NUXT_OAUTH_KEYCLOAK_REALM=larex-prod
NUXT_OAUTH_KEYCLOAK_CLIENT_ID=larex-frontend
NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET=your-frontend-client-secret
NUXT_OAUTH_KEYCLOAK_REDIRECT_URL=https://app.example.org/auth/keycloak

Example: Production-Like Local (compose.prod.local.yaml)

# Optional: most values have local defaults in compose.prod.local.yaml
NUXT_SESSION_PASSWORD=replace-with-random-32-plus-character-secret
KEYCLOAK_ADMIN_CLIENT_SECRET=PLEASE_CHANGE_IN_PRODUCTION
NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET=PLEASE_CHANGE_IN_PRODUCTION

Resource Limits

Modify resource limits in the relevant compose file (compose.prod.yaml, compose.prod.traefik.yaml, etc.) under deploy.resources.

Security Considerations

Sensitive Variables

Never commit these to version control:

  • POSTGRES_PASSWORD
  • KEYCLOAK_ADMIN_PASSWORD
  • KEYCLOAK_ADMIN_CLIENT_SECRET
  • NUXT_SESSION_PASSWORD
  • NUXT_OAUTH_KEYCLOAK_CLIENT_SECRET
  • MAIL_PASSWORD

Use a secrets management tool or Docker secrets for production.

Variable Security

# Use environment file with restricted permissions
chmod 600 .env.prod

Validation

Verify variables are set correctly:

# Check configured variables
grep -E "^[A-Z_]+=.+$" .env.prod | sort

# Validate compose variants with explicit env files
docker compose --env-file .env.prod -f compose.prod.yaml config
docker compose --env-file .env.prod.external-keycloak -f compose.prod.external-keycloak.yaml config
docker compose --env-file .env.prod.traefik -f compose.prod.traefik.yaml config
docker compose --env-file .env.prod.local -f compose.prod.local.yaml config
Copyright © 2026