Self-hosting
Grow the dev container into a production deployment — one step at a time, each a runnable compose.
Uptimer scales from one command to a split, migrated, Postgres-backed cluster. Each step below is
a complete, runnable docker-compose.yml plus the reason for it — add only the steps you
need; each hardens the one before.
1 · Dev — one command
docker run -p 2517:2517 ghcr.io/myuptime-info/uptimer:1.3.0
The default dev command runs every service in one process, with fake auth (any visitor is an
admin) and an in-memory database. Nothing survives a restart — fine for a look. Everything below
makes it real.
2 · Persist data
Data (the SQLite database and the server/worker identity keys) must outlive the container. Mount
a volume at /data:
# docker-compose.yml
services:
uptimer:
image: ghcr.io/myuptime-info/uptimer:1.3.0
ports: ["2517:2517"]
volumes: ["uptimer-data:/data"]
volumes:
uptimer-data:
docker compose up. See Persistent storage for what lives in
/data and how to mount a custom config.
3 · A real database
SQLite is dev-only — its schema is auto-migrated and not guaranteed safe across upgrades. Add PostgreSQL for versioned, upgrade-safe migrations:
# docker-compose.yml
services:
db:
image: postgres:17
environment:
POSTGRES_USER: uptimer
POSTGRES_PASSWORD: secret
POSTGRES_DB: uptimer_server
volumes: ["pg:/var/lib/postgresql/data"]
uptimer:
image: ghcr.io/myuptime-info/uptimer:1.3.0
ports: ["2517:2517"]
environment:
UPTIMER__SERVER__DB__DSN: "postgres://uptimer:secret@db:5432/uptimer_server?sslmode=disable"
depends_on: [db]
volumes:
pg:
Still one process and still dev auth — but your data is now on a real database. Runnable:
examples/1.3.0/persistent.
Background: Choosing a database.
4 · Real authentication
Dev auth logs everyone in as an admin. Turn it off and add OIDC to the uptimer service from
step 3:
environment:
UPTIMER__SERVER__DB__DSN: "postgres://uptimer:secret@db:5432/uptimer_server?sslmode=disable"
UPTIMER__SERVER__AUTH__DEV: "false"
UPTIMER__SERVER__AUTH__OIDC__ISSUER_URL: "https://id.example.com/realms/main"
UPTIMER__SERVER__AUTH__OIDC__CLIENT_ID: "uptimer"
UPTIMER__SERVER__AUTH__OIDC__CLIENT_SECRET: "…"
UPTIMER__SERVER__AUTH__OIDC__REDIRECT_URL: "https://uptimer.example.com/ui/auth/oauth/callback"
A complete, runnable Keycloak + Uptimer stack is in Authentication → Keycloak.
5 · Split into services
In production the server runs as separate processes — api,ui, grpc, availabilities, plus
workers — so each scales and restarts independently, and a one-shot migrate job owns schema
changes. The full topology, as one docker-compose.yml, is on the
Production deployment page.
Stop at whichever step fits — a single persistent container with PostgreSQL and OIDC is a perfectly good small deployment.