Quickstart
You need: Docker Engine with the Compose v2 plugin (docker compose version prints
2.x; the older standalone docker-compose is not supported), curl, and a Linux or macOS
host — the stack runs as your own user id (id -u / id -g), which Docker Desktop on
Windows/WSL also provides.
-
Get the compose file
Terminal window curl -fsSL https://raw.githubusercontent.com/Strandgaard96/mc-gamertime/main/docker-compose.yml -o docker-compose.ymlNo clone needed — this one file is the whole self-host setup.
-
Set your admin credentials
Create a file named
.envnext todocker-compose.ymlcontaining:Terminal window ADMIN_USERNAME=adminADMIN_PASSWORD=<your-password>Use at least 12 characters — the first-boot bootstrap does not check, but every later password change does. Compose auto-loads
.envfrom the same directory. The first boot creates this admin account; afterwards the variables are ignored, so an existing password is never overwritten. Once you have logged in, delete both lines again so the password isn’t left on disk in plain text. -
Start the stack
Terminal window docker compose up -dPulls the pre-built image from GHCR and creates the SQLite database and storage directory under
./config/app/on first run. Wait a few seconds for themc-gamertimecontainer to become healthy.Image tags:
latestandX.Y.Zfollow releases;mainis the edge build from every commit. Pinimage: ghcr.io/strandgaard96/mc-gamertime:X.Y.Zindocker-compose.ymlif you want to control when you upgrade. -
Open the app
Navigate to
http://localhost:4263and log in.That works on the host itself only: the port is bound to
127.0.0.1by default. To open it from a phone or another machine on your LAN, addAPP_BIND=0.0.0.0to.envand rundocker compose up -dagain — see Configuration → Host port and bind address for what that exposes.
What’s running
Section titled “What’s running”| Container | Role | Port (internal) |
|---|---|---|
mc-gamertime |
FastAPI + React frontend, embedded SQLite, local filesystem storage | 4263 |
mc-gamertime-init |
One-shot, fixes ownership on config/app then exits |
none |
Only mc-gamertime is exposed, at 127.0.0.1:4263 on the host (loopback only unless you set APP_BIND).
docker-compose.yml
Section titled “docker-compose.yml”services: mc-gamertime-init: container_name: mc-gamertime-init image: alpine:3 user: root command: >- sh -c "mkdir -p /config/app && chown -R ${PUID:-1000}:${PGID:-1000} /config/app" volumes: - ./config:/config restart: "no" deploy: resources: limits: memory: 32m cpus: "0.1" security_opt: - no-new-privileges:true cap_add: - CHOWN - DAC_OVERRIDE cap_drop: [ALL]
mc-gamertime: container_name: mc-gamertime image: ghcr.io/strandgaard96/mc-gamertime:latest # Must match init's chown target above, or the app can't write /data. user: "${PUID:-1000}:${PGID:-1000}" ports: # APP_BIND=127.0.0.1 (default) keeps the port loopback-only for a reverse proxy on # this host; APP_BIND=0.0.0.0 exposes it to the LAN. Docker port bindings bypass # ufw/firewalld, so this line is the only firewall the app has. - "${APP_BIND:-127.0.0.1}:${APP_PORT:-4263}:4263" environment: DB_BACKEND: sqlite STORAGE_BACKEND: local SECRETS_PROVIDER: env ORIGIN_GUARD_ENABLED: "false" PUBLIC_RECOMMENDED_ENABLED: "false" BGG_TOKEN: ${BGG_TOKEN:-} ADMIN_USERNAME: ${ADMIN_USERNAME:-} ADMIN_PASSWORD: ${ADMIN_PASSWORD:-} APP_BASE_URL: ${APP_BASE_URL:-} SMTP_HOST: ${SMTP_HOST:-} SMTP_PORT: ${SMTP_PORT:-587} SMTP_USERNAME: ${SMTP_USERNAME:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} SMTP_FROM_ADDRESS: ${SMTP_FROM_ADDRESS:-} METRICS_ENABLED: ${METRICS_ENABLED:-false} FORWARDED_ALLOW_IPS: ${FORWARDED_ALLOW_IPS:-} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-} volumes: - ./config/app:/data restart: unless-stopped depends_on: mc-gamertime-init: condition: service_completed_successfully deploy: resources: limits: memory: 512m cpus: "1.0" reservations: memory: 128m cpus: "0.25" security_opt: - no-new-privileges:true cap_drop: [ALL]Next steps
Section titled “Next steps”- Configuration — BGG token for game search, password reset email, metrics
- HTTPS / Reverse proxy — before exposing it beyond your LAN
- Backups & upgrades