Sections

Install with Docker

Run Frontdoor with Docker Compose, with persistent storage and Microsoft Entra sign-in.

On this page

Frontdoor ships as a single container with an embedded SQLite database. Express serves both the web app and the API on port 3001.

Requirements

  • Docker with Docker Compose 2.24 or later (the compose file passes your .env with env_file).
  • A Microsoft Entra app registration with its client ID, client secret and tenant ID, or the local demo mode below. See Microsoft Entra setup.
  • A checkout of the Frontdoor repository: the image is built from it.

Try it locally without Entra

The demo profile needs no .env file and no Microsoft Entra registration:

docker compose -f docker-compose.demo.yml up --build

Open http://localhost:3001 and use the Dev Login panel to sign in as owner, admin, admin_readonly or user. The demo profile uses its own data volume and publishes the port on 127.0.0.1 only.

Dev Login lets anyone pick any role and signs tokens with a public fallback secret. Never expose this profile to a network or put it behind a reverse proxy. Remove it with:

docker compose -f docker-compose.demo.yml down -v

Configure the environment

Copy the Docker example file and fill in your values:

cp .env.example.docker .env
BASE_DOMAIN=frontdoor.contoso.com
FRONTEND_URL=https://frontdoor.contoso.com
AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
AZURE_CLIENT_SECRET=your-client-secret
AZURE_TENANT_ID=00000000-0000-0000-0000-000000000000
AZURE_REDIRECT_URI=https://frontdoor.contoso.com/api/auth/microsoft/callback
JWT_SECRET=a-unique-random-value-of-at-least-32-characters
ADMIN_EMAILS=alice@contoso.com

ADMIN_EMAILS lists the owners, promoted automatically when they sign in. Every variable is described in the Configuration reference. PORT, DATABASE_PATH and the /data folders are set by docker-compose.yml and cannot be changed from .env; NODE_ENV is always production, so Dev Login is off.

Start the container

docker compose up -d

The first run builds the image. Open your FRONTEND_URL (or http://localhost:3001 on the same machine) and sign in with Microsoft. If a required value is missing or malformed, the container stops at startup with a clear log entry:

docker compose logs frontdoor

To record the commit in backups, pass it at build time:

COMMIT_SHA=$(git rev-parse --short HEAD) docker compose build

With plain docker build, use --build-arg COMMIT_SHA=... instead.

Persistent data

Every writable path lives on the frontdoor-data volume mounted at /data: the database (/data/frontdoor.db), avatars, app icons, branding and plugin files. Data survives image upgrades. A healthcheck calls /api/health every 30 seconds, and the container restarts unless you stop it.

To prewarm the avatar cache for existing users, run the utility as the app user so the cached files keep the right owner:

docker compose exec -u frontdoor frontdoor npm run avatars:prewarm

Fetching Microsoft 365 photos this way needs the Microsoft Graph permission ProfilePhoto.Read.All (see Microsoft Entra setup).

Production checklist

Set at least:

  • 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 (true by default in docker-compose.yml)
  • CORS_ALLOWED_ORIGINS only if a page or satellite app on another origin must call Frontdoor with credentials

Recommended: ADMIN_EMAILS, ADMIN_API_KEY and JWT_EXPIRES_IN. If a reverse proxy sits in front of Frontdoor, give it a body size limit that matches BACKUP_MAX_UPLOAD_MB (default 1024).

Upgrade

  1. Download a backup from Customize → Maintenance.
  2. Pull or build the new version and start it on the same volume: docker compose up -d --build. Migrations run at startup.
  3. Sign in, open the admin pages and, with ENTRA_GROUP_SYNC=true, run a Force Sync.
  4. If something goes wrong, start the previous image and restore the backup.

For the full procedure, including a rehearsal on a copy of your data, see Upgrade and rollback.