Install

OpenFault is one container. Everything it keeps (the SQLite database and its generated secret) lives in /data.

OpenFault is in early development. Run it next to Sentry before you switch off Sentry.

docker run

docker run -d --name openfault -p 8080:8080 -v openfault-data:/data ghcr.io/openfault/openfault:latest

Open http://localhost:8080. The first visit runs a setup wizard that creates the admin and the first project.

Compose

services:
  openfault:
    image: ghcr.io/openfault/openfault:latest
    ports:
      - "8080:8080"
    volumes:
      - openfault-data:/data
    environment:
      OPENFAULT_BASE_URL: https://errors.example.com
    restart: unless-stopped

volumes:
  openfault-data:

Environment variables

All optional. Everything else is set in Settings.

VariableDefaultMeaning
OPENFAULT_DATA/data in the imageDirectory for openfault.db and the generated secret.
OPENFAULT_PORT8080HTTP listen port.
OPENFAULT_BASE_URLfrom the Host headerPublic URL for DSNs and links in emails, pushes and webhooks. An https:// value also marks session cookies Secure. Required when SMTP is set.
OPENFAULT_SMTP_URLoffOutgoing email. See Notifications.
OPENFAULT_TRUST_PROXYoff1 uses the first X-Forwarded-For address for login and pairing rate limits. Set it only behind your own proxy.
OPENFAULT_ALLOW_PRIVATE_WEBHOOKSoff1 allows webhook URLs on private, local and loopback addresses.
OPENFAULT_PUSH_RELAY_URLoffPush relay for the iOS app. See Push & iOS app.
OPENFAULT_PUSH_RELAY_TOKENoffBearer token for that relay.
RUST_LOGinfoLog filter.

Reverse proxy (HTTPS and HTTP/2)

Put OpenFault behind a proxy that terminates HTTPS. HTTPS gets you HTTP/2, and that matters: every open tab holds one live-update connection, and browsers on HTTP/1.1 allow only 6 per host, so the seventh tab stalls.

Caddy does it in three lines and gets the certificate for you:

errors.example.com {
  reverse_proxy localhost:8080
}

Then set OPENFAULT_BASE_URL=https://errors.example.com so DSNs and links use the public address.

Upgrade

Pull the new image and restart. Migrations run on boot.

docker pull ghcr.io/openfault/openfault:latest
docker stop openfault && docker rm openfault
docker run -d --name openfault -p 8080:8080 -v openfault-data:/data ghcr.io/openfault/openfault:latest

With Compose: docker compose pull && docker compose up -d.

Backup

The database runs in SQLite WAL mode, so a copy taken while it is writing can miss the newest pages. The image is distroless and has no sqlite3 shell. The safe path: stop, copy the volume, start.

docker stop openfault
docker run --rm -v openfault-data:/data -v "$PWD":/backup alpine tar czf /backup/openfault-$(date +%F).tgz -C /data .
docker start openfault

SDKs retry while it is down, and the stop takes seconds. Restore by extracting the archive into an empty volume. Upgrade and backup notes in the README are still being written; check it before a major upgrade.