Run the server¶
The server keeps the tracker in a SQLite database behind an HTTP API, with sign-in. It also serves the standalone tracker at /standalone/ for people who prefer a page that needs no server.
With Docker Compose¶
The container is published through Traefik; create the network Traefik is attached to once, then start the service:
docker network create traefik # once
cp .env.example .env # set SUFS_TRACKER_HOSTNAME and the Traefik entrypoint/TLS there
docker compose up --build -d
docker compose exec sufs-tracker sufs-tracker user create NAME
compose.yaml on its own is the production setup: no host port, reachable only at https://<SUFS_TRACKER_HOSTNAME>/ through Traefik. The database lives in the data volume at /data/sufs-tracker.db.
The project's CI pushes a ready image to the GitLab instance's container registry on every change to the default branch. To run it instead of building locally, set SUFS_TRACKER_IMAGE in .env to that image (<registry>/<group>/sufs-tracker:latest).
For local development add the override, which mounts the source, reloads on Python edits and publishes the port on 127.0.0.1 (SUFS_TRACKER_PORT, default 8000):
docker compose -f compose.yaml -f compose.dev.yaml up --build --watch
Put COMPOSE_FILE=compose.yaml:compose.dev.yaml in .env to make plain docker compose up --build pick it. The pages are generated when the server starts, so after editing sufs_tracker/page/ run docker compose restart; --watch rebuilds the image when Dockerfile, pyproject.toml or uv.lock change.
Podman works the same way: podman compose up --build -d and podman compose exec ….
Without Docker¶
uv sync
uv run sufs-tracker init # creates sufs-tracker.db (also happens on startup)
uv run sufs-tracker user create NAME
uv run uvicorn sufs_tracker.server.app:app # http://127.0.0.1:8000/
The pages are generated when the server starts, so there is nothing to build beforehand. To serve this documentation at /docs/ as well, build it once with uv run --only-group docs zensical build (the container image includes it).
Behind a reverse proxy¶
Put the server behind your TLS proxy. The session cookie is marked Secure only when the request arrives over https, so tell uvicorn to trust the proxy's X-Forwarded-Proto header:
uvicorn sufs_tracker.server.app:app --proxy-headers --forwarded-allow-ips='<proxy ip>'
compose.yaml already sets FORWARDED_ALLOW_IPS=* for this, which is safe because the container is only reachable through Traefik.
Checking it's up¶
GET /api/health returns {"ok": true} once the database is reachable. compose.yaml runs it as the service's health check. Interactive API docs are at /api/docs.
Settings¶
See Configuration for the environment variables (SUFS_DB_PATH, SUFS_STATIC_DIR). Then create the first login and set up backups.