Skip to content

Operations Runbook

This runbook is for deployers and maintainers. It assumes the Docker deployment described in Docker Compose.

Service Inventory

Service Default endpoint Persistent state
BillTracker app http://<host>:3030 /portainer/hosting/bill-tracker/data:/data
BillTracker docs http://<host>:8055 /portainer/hosting/bill-tracker/mkdocs:/docs

BillTracker stores its live database at /data/db/bills.db inside the app container and managed backups at /data/backups.

Start Or Recreate App

From the app Compose directory:

docker compose pull
docker compose up -d

Confirm:

docker ps --filter name=bill-tracker
docker logs --tail 100 bill-tracker
curl -fsSI http://127.0.0.1:3030/
curl -fsS http://127.0.0.1:3030/api/about

The app root should return 200. /api/about should return the running version.

Start Or Recreate Docs

The docs container mounts the MkDocs project at /docs and runs:

mkdocs serve --dev-addr=0.0.0.0:8000

To validate docs before restart:

docker run --rm \
  -v /portainer/hosting/bill-tracker/mkdocs:/docs \
  squidfunk/mkdocs-material:latest \
  build --strict

Then:

docker restart billtracker-docs
curl -fsSI http://127.0.0.1:8055/

Before Upgrade

  1. Open Admin and create a manual backup.
  2. Download the backup or copy /data/backups to protected storage.
  3. Record the current app version from /api/about.
  4. Confirm the current Status page does not already show a database error.
  5. Pull and recreate the container.
  6. Confirm migrations complete in logs.
  7. Validate login and the Status page.

Database Health

Use the Admin Status page first. For a direct SQLite integrity check, stop writes or work from a backup copy:

sqlite3 /data/db/bills.db 'PRAGMA integrity_check;'

Expected result:

ok

Backup Recovery

Preferred recovery path:

  1. Use Admin backup restore.
  2. Select the intended managed backup.
  3. Confirm restore.
  4. Record the returned pre-restore backup identifier.
  5. Verify login and Status.

If the UI is unavailable, preserve the current database, WAL, and SHM files before manual intervention. Do not overwrite the only copy of the live database.

Login Incident

Local Login Fails

Check:

  1. /api/auth/mode still reports local login enabled.
  2. The user is active.
  3. The account is a local account rather than OIDC-only.
  4. The browser receives bt_session after successful login.
  5. Secure cookies are not being tested over plain HTTP.

OIDC Login Fails

Check:

  1. Issuer URL resolves from the BillTracker host.
  2. Redirect URI exactly matches the provider.
  3. Client ID and secret are current.
  4. Provider discovery endpoint is reachable.
  5. openid email profile groups scopes are available.
  6. The configured admin group matches the provider claim spelling.
  7. Local login remains enabled while repairing OIDC.

CSRF Incident

Symptom:

CSRF token validation failed

Check:

  1. Browser has bt_csrf_token set.
  2. SPA has a valid in-memory token from GET /api/auth/csrf-token.
  3. SPA sends x-csrf-token on the mutating request.
  4. CSRF_HTTP_ONLY=true is the default and is fine for the SPA flow.
  5. Proxy and HTTPS cookie behavior are correct (X-Forwarded-Proto: https or trust proxy set when TLS terminates upstream).
  6. The user refreshed after a stale browser session.

Do not disable CSRF to make the symptom disappear.

SimpleFIN Incident

Check:

  1. Admin bank sync flag is enabled.
  2. User connection still exists.
  3. The source last_error on Status.
  4. The connection was not synced within the worker's 1-hour skip window.
  5. Setup access has not been revoked.
  6. Selected accounts remain monitored.
  7. A manual Sync Now succeeds before using backfill.

Disconnect and reconnect only after reviewing the stored source error.

Notification Incident

Check:

  1. SMTP is enabled.
  2. Host, port, and sender address are present.
  3. Password exists when SMTP username is set.
  4. TLS mode matches the server.
  5. Run the Admin test email action.
  6. Confirm user or global-recipient preferences.
  7. Review notification errors on Status.

Disk And Cleanup Incident

Review:

df -h
du -sh /portainer/hosting/bill-tracker/data/*

Then use Admin cleanup. Cleanup can remove stale preview sessions, temp exports, partial backup files, optional old import history, and soft-deleted bills or categories after the 30-day recovery window.

Logs

Useful commands:

docker logs --tail 200 bill-tracker
docker logs --since 30m bill-tracker
docker logs --tail 100 billtracker-docs

Avoid publishing logs without reviewing them for usernames, transaction descriptions, filenames, or infrastructure details.

Post-Change Verification

Run:

npm test
npm run check

For docs:

docker run --rm \
  -v "$PWD/mkdocs:/docs" \
  squidfunk/mkdocs-material:latest \
  build --strict

Then test representative live endpoints and inspect the Status page.