Skip to content

Deployment

Rod Christiansen edited this page Oct 8, 2026 · 4 revisions

Deployment

The dashboard ships as a container image. It is a stateless Node process: it needs a reachable reportmate-api, the shared secret, and its auth configuration. It needs no database of its own.

Published image

Tagging a release publishes ghcr.io/reportmate/web from .github/workflows/ghcr-publish.yml. The workflow triggers on tags matching v* or a YYYY.MM.DD.HHMM datestamp, and also runs on manual dispatch. Each tag run pushes the tag plus latest; a manual run pushes latest only.

Merging to main publishes nothing; an image exists only for a tag. The most recent tag is 2026.09.16.1139, so features merged after it (the Storage status, the per-drive Hardware storage column) are on main but not yet in a published image.

The image is consumed by selfhosted-docker-reportmate, which is the supported way to run the full stack.

Building it yourself

docker build -t reportmate-web .
docker run -p 3000:3000 \
  -e API_BASE_URL=https://api.example.com \
  -e API_INTERNAL_SECRET=replace-me \
  -e NEXTAUTH_SECRET=replace-me \
  -e NEXTAUTH_URL=https://reportmate.example.com \
  -e AZURE_AD_CLIENT_ID=replace-me \
  -e AZURE_AD_CLIENT_SECRET=replace-me \
  -e AZURE_AD_TENANT_ID=replace-me \
  -e ALLOWED_DOMAINS=example.com \
  reportmate-web

The Dockerfile is a multi-stage build (deps, builder, runner) on a shared node:20-alpine base with pnpm pinned to 10.34.5 — the pin is load-bearing, since newer pnpm requires a newer Node than the base image and fails the build. It builds with output: 'standalone' and the runtime stage runs node server.js as a non-root nextjs user on port 3000.

Build arguments

Anything that must be baked into the client bundle has to be a build argument, because NEXT_PUBLIC_ values are inlined at build time. The Dockerfile accepts IMAGE_TAG, BUILD_TIME, BUILD_ID, API_BASE_URL, NEXT_PUBLIC_API_BASE_URL, ENABLE_SIGNALR, WPS_URL and NEXT_PUBLIC_DEMO_MODE. The version-metadata ones are also re-exported into the runtime stage so /api/version reports the deployed tag rather than the package.json version.

Server-side settings — API_INTERNAL_SECRET, NEXTAUTH_SECRET, the identity provider credentials, KIOSK_TOKENS — are runtime environment variables. Never pass a secret as a build argument; it ends up in the image history.

Behind a proxy or CDN

Set NEXTAUTH_URL to the public URL. The auth callbacks, the sign-in redirect and the kiosk redirect all rewrite the host from it, and without it they point at the container's own address.

Register <public URL>/api/auth/callback/azure-ad as a redirect URI with the identity provider.

Health checks

Path Auth Use
/api/healthz Public Liveness and readiness. Also reports whether API_BASE_URL and the internal secret are set
/api/version Public Deployed version, build id, build time, image tag
/api/diagnostic Session Actually calls the upstream devices and events endpoints

Point a load balancer at /api/healthz; it is in the middleware's bypass list and answers both GET and HEAD.

Infrastructure

Cloud infrastructure is declared in the Terraform modules (Azure, AWS), which is where resource definitions, app settings and role assignments belong. The deploy.md file in the repo describes imperative deploy.sh / deploy.ps1 scripts that are not in the tree; do not follow it.

Clone this wiki locally