Repository navigation
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.
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.
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.
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.
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.
| 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.
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.
AGPL-3.0 · reportmate.app