Sections

Configuration reference

Every Frontdoor environment variable with its default, the production checklist, cross-origin session checks and the startup log.

On this page

Frontdoor reads its configuration from environment variables, usually through a .env file. Two examples ship with the project: .env.example.docker for Docker and .env.example.node for Node.js.

With Docker, docker-compose.yml sets NODE_ENV, PORT, DATABASE_PATH and the /data folders itself; those cannot be changed from .env.

Environment variables

Server and storage

Variable Description Default
NODE_ENV production disables Dev Login and enables secure cookies - (production in Docker)
PORT Express server port 3001
DATABASE_PATH SQLite file path ./frontdoor.db
AVATAR_CACHE_DIR Disk cache for user avatars and metadata ./data/avatar-cache
APP_ICON_CACHE_DIR Disk cache for uploaded app icons and pasted SVG assets ./data/app-icon-cache
BRANDING_ASSET_DIR Disk storage for the optional company logo ./data/branding
PLUGIN_ASSET_DIR Disk storage for plugin packages (plugin system currently locked off) ./data/plugins
BACKUP_MAX_UPLOAD_MB Largest backup file accepted by Check backup and restore. Uploads are streamed to a temporary file, not held in memory. A reverse proxy in front of Frontdoor needs a matching body size limit 1024
AVATAR_CACHE_TTL_DAYS Refresh interval for cached Microsoft 365 / Gravatar avatars 14
AVATAR_CACHE_MISS_TTL_DAYS Retry interval when no avatar was found 30
TIMEZONE (or TZ) Server time zone used for log timestamps. The default for the UI is set in Customize UTC
COMMIT_SHA Commit recorded in backups (Docker build argument) -

Domain and origins

Variable Description Default
BASE_DOMAIN Base domain, without protocol frontdoor.local
FRONTEND_URL Frontend URL with protocol. Also trusted as origin for requests that change data https://frontdoor.local
CORS_ALLOWED_ORIGINS Comma-separated allowlist of origins that can call Frontdoor with credentials: 'include', for shared-cookie or session-check pages. Leave empty to disable CORS -

Sign-in and sessions

Variable Description Default
DEV_LOGIN Enable local Dev Login without Microsoft SSO (ignored in production) false
AZURE_CLIENT_ID Application (client) ID of the Entra app registration -
AZURE_CLIENT_SECRET Client secret of the Entra app registration -
AZURE_TENANT_ID Directory (tenant) ID -
AZURE_REDIRECT_URI SSO callback redirect URI https://frontdoor.local/api/auth/microsoft/callback
JWT_SECRET JWT signing secret -
JWT_EXPIRES_IN JWT token duration 7d
JWT_ISSUER Issuer of the session and SSO tokens. Satellite apps that verify tokens must use the same value frontdoor
IMPERSONATION_TIMEOUT_MINUTES Minutes an admin can act as a user before the impersonation ends (clamped to 5–240) 30
ADMIN_EMAILS Comma-separated owner emails, promoted automatically -
ADMIN_API_KEY API key for the bulk endpoints -

Microsoft Entra groups and notifications

Variable Description Default
ENTRA_GROUP_SYNC Discover Entra group memberships at sign-in and enable the admin import and sync flows false (true in docker-compose.yml)
ENTRA_TENANT_REFRESH_MINUTES Minimum minutes between two refreshes of the tenant-wide Entra group catalog triggered by sign-ins. A manual sync always refreshes it; 0 refreshes at every sign-in 360
ENTRA_DELETED_GROUP_POLICY What happens to the members of an Entra group that Microsoft Entra reports deleted: freeze keeps their access until an admin decides; revoke removes it at the next sign-in or sync. Both flag the group, keep a snapshot and notify admins freeze
NOTIFICATION_RETENTION_DAYS Days a resolved admin notification is kept before the daily purge removes it 30

Rate limits

All limits are per IP address.

Variable Description Default
AUTH_RATE_LIMIT_MAX / AUTH_RATE_LIMIT_WINDOW_MS Microsoft sign-in endpoints 5000 / 15 min
RBAC_RATE_LIMIT_MAX / RBAC_RATE_LIMIT_WINDOW_MS Group and user changes 500 / 15 min
API_RATE_LIMIT_MAX / API_RATE_LIMIT_WINDOW_MS The rest of the API 6000 / 15 min

Production checklist

For a real deployment, set at least:

  • NODE_ENV=production (already set by docker-compose.yml; Dev Login is always off in production)
  • BASE_DOMAIN and FRONTEND_URL
  • AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID and AZURE_REDIRECT_URI
  • a unique JWT_SECRET of at least 32 characters
  • ENTRA_GROUP_SYNC if you want Entra group sync
  • CORS_ALLOWED_ORIGINS if a static page or satellite app on another origin must call Frontdoor with credentials

Recommended:

  • ADMIN_EMAILS
  • ADMIN_API_KEY
  • JWT_EXPIRES_IN
  • a tenant default time zone in Customize, if you want something other than UTC

If a required value is missing or malformed, Frontdoor stops at startup with a clear log entry instead of failing later with an authentication error.

Cross-origin session checks

CORS_ALLOWED_ORIGINS is meant for pages that only need to know whether the user already has an active Frontdoor session: for example a plain static page or a download page on a sibling domain.

If you host a page on https://contoso.com, set:

CORS_ALLOWED_ORIGINS=https://contoso.com

The page can then ask Frontdoor whether the browser session is authenticated:

<script>
  async function checkSession() {
    const response = await fetch('https://frontdoor.contoso.com/api/auth/me', {
      credentials: 'include',
    });

    if (response.ok) {
      const { user } = await response.json();
      console.log('Signed in as:', user.email || user.displayName);
      return;
    }

    window.location.href = 'https://frontdoor.contoso.com/login';
  }

  checkSession().catch(() => {
    window.location.href = 'https://frontdoor.contoso.com/login';
  });
</script>

credentials: 'include' tells the browser to send the frontdoor_token cookie with the request. Frontdoor accepts the cross-origin request only if the page's origin is listed in CORS_ALLOWED_ORIGINS.

Startup log

At startup the server prints a redacted summary of its configuration:

Frontdoor startup configuration:
  NODE_ENV=production
  PORT=3001
  DATABASE_PATH=/data/frontdoor.db
  BRANDING_ASSET_DIR=/data/branding
  BASE_DOMAIN=contoso.com
  FRONTEND_URL=https://frontdoor.contoso.com
  CORS_ALLOWED_ORIGINS=[empty]
  TIMEZONE=UTC
  DEV_LOGIN=disabled
  AZURE_CLIENT_ID=[set]
  AZURE_CLIENT_SECRET=[set]
  AZURE_TENANT_ID=[set]
  AZURE_REDIRECT_URI=https://frontdoor.contoso.com/api/auth/microsoft/callback
  JWT_SECRET=[set]
  ADMIN_EMAILS=1 owner configured

Warnings point out defaults and weak but valid settings, for example:

  • BASE_DOMAIN is not set, defaulting to frontdoor.local
  • JWT_SECRET is shorter than 32 characters; use a longer random secret in production