Skip to content

Troubleshooting

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

Troubleshooting

Failure modes you can trace to something in this repo. Start by looking at the containers:

docker compose ps

Then the logs for one service:

docker compose logs -f api

Compose refuses to start: "set DB_PASSWORD in .env"

error while interpolating services.postgres.environment.POSTGRES_PASSWORD: required variable DB_PASSWORD is missing a value: set DB_PASSWORD in .env

Four variables use Compose's :? syntax and have no default: DB_PASSWORD, API_INTERNAL_SECRET, REPORTMATE_PASSPHRASE, NEXTAUTH_SECRET. The message names whichever one is empty. You are either missing .env entirely (cp .env.example .env) or running docker compose from a directory other than the one holding .env.

api restarts in a loop with a Postgres authentication failure

The password in DATABASE_URL is built from DB_PASSWORD, but POSTGRES_PASSWORD only takes effect when Postgres initialises an empty data directory. Changing DB_PASSWORD in .env after the first start leaves the volume holding the old password, and the API can no longer connect.

Either put the original password back in .env, or change it inside Postgres:

docker compose exec postgres psql -U reportmate -d reportmate -c "ALTER ROLE reportmate WITH PASSWORD 'new-password';"

Then set the same value in .env and docker compose up -d. Wiping the volume also works and destroys all data.

Dashboard loads but every panel is empty

The browser calls the dashboard's own routes, and the dashboard calls the API server-side at http://api:8000, so an empty dashboard is a web to api problem, not a browser or CORS one. Check, in order:

  • The API is up and healthy: curl http://localhost:8000/api/v1/health.
  • API_INTERNAL_SECRET matches on both containers (see below).
  • The web log shows the failing request:
docker compose logs -f web

Tables missing, or relation "devices" does not exist

schema/init.sql is mounted into /docker-entrypoint-initdb.d and Postgres runs that directory only when the data directory is empty. If a volume was created before the schema file existed, or the bind mount path was wrong at first start, the database came up empty and stayed that way.

Confirm what is in there:

docker compose exec postgres psql -U reportmate -d reportmate -c "\dt"

If the tables are genuinely absent and there is no data to lose, docker compose down -v followed by docker compose up -d re-runs the init script. If there is data, apply the file by hand instead:

docker compose exec -T postgres psql -U reportmate -d reportmate < schema/init.sql

Its tables, indexes, and columns all use IF NOT EXISTS, so re-running is safe for those. The CREATE TRIGGER statements near the end do not — Postgres has no IF NOT EXISTS for triggers — so on a database that already has them you will see trigger "update_devices_updated_at" for relation "devices" already exists and the script stops there. Drop the existing triggers first, or run the file in pieces.

Agents get 401 / 403 posting to the API

The passphrase the agent sends must be one of the values in REPORTMATE_PASSPHRASE. The API accepts a comma-separated list there, so during rotation keep the old value in the list until every endpoint has the new one.

Check what the running container actually has, rather than what you think you put in .env:

docker compose exec api printenv REPORTMATE_PASSPHRASE

Dashboard errors on its own API calls

API_INTERNAL_SECRET must be byte-identical on api and web. The Compose file wires both from one .env value, so a mismatch means one of the containers is stale — it was created before you last edited .env. Recreate both:

docker compose up -d --force-recreate api web

Sign-in page appears even though DEMO_MODE=true

The published ghcr.io/reportmate/web image has demo mode compiled off, so DEMO_MODE in .env has no effect. Configure an identity provider, or build a demo-mode dashboard image. See Configuration.

api never starts, postgres sits at "starting"

api uses condition: service_healthy, so it waits for pg_isready. If Postgres never turns healthy, read its log:

docker compose logs postgres

A common cause is an error inside schema/init.sql on a first start — Postgres aborts initialisation and the container will not become healthy. The failing statement appears in that log.

Packer build fails

packer/setup.sh runs with set -euo pipefail, so the first failing command ends the build and the failing line is in the output. The usual causes are no network from the build VM when adding the Docker apt repository, or no KVM on the build host (the qemu source sets accelerator = "kvm").

CI runs shellcheck --severity=error packer/setup.sh, packer validate, and docker compose config --quiet, so syntax problems in a pull request are caught before this point.

Appliance came up with unknown secrets

first-boot.sh generated them because no .env was present. Read them off the booted machine:

sudo cat /opt/reportmate/.env

The three application secrets will be the same string; see Appliance Image.

Clone this wiki locally