Self-hosting
Run the whole platform on your own hardware — API, Postgres, web app, and your own tiles.
Self-hosting is a supported product, not a README promise: the compose stack boots and passes smoke tests in CI, and any design that would break single-box self-hosting gets rejected. Self-hosters get every feature ungated — sync, offline, sharing — because paid plans sell hosted convenience, not capability.
A full deployment is three pieces:
- The API + Postgres — accounts, sync, sharing.
- The web app — the map workspace.
- Tiles — static PMTiles you generate with the pipeline for the states you hunt.
Quickstart: API + Postgres
cd deploy/compose
docker compose up -dThat brings up Postgres (PostGIS image) and the API on
http://localhost:8080, with migrations applied automatically. Verify with:
curl http://localhost:8080/healthzThe full single-box stack
deploy/homelab runs everything — Postgres, the API, the background
worker, and the web app — localhost-bound so it can't collide with anything
else on the box:
cd deploy/homelab
./deploy.sh # build, migrate, start, verify — idempotentEndpoints: web on http://localhost:3200, API on http://localhost:8090.
Postgres data persists in a named volume; tiles bind-mount read-only from
the repo's tiles directory, so regenerating them is a pipeline run plus a
web-container restart (the web tier snapshots its public directory at
startup).
Updating is git pull && ./deploy.sh — it rebuilds changed layers,
restarts, and re-verifies.
Bringing your own tiles
The API never serves tiles — map data is static files. Run the
pipeline for your states and drop the resulting
.pmtiles in the tiles directory the web tier serves. Published OpenHunt
artifacts are also freely downloadable, so you can start from those instead
of processing raw sources yourself.
Exposing it with a hostname
Put a reverse proxy (traefik, Caddy, nginx) in front of the web and API containers, then:
- set
COOKIE_SECURE=trueon the API, - set
ALLOWED_ORIGINSto your web origin (e.g.https://hunt.example.com), - rebuild the web app with
NEXT_PUBLIC_API_URLpointing at the API's public URL.
The configuration reference covers every variable.
Sizing
Boring tech on purpose: one Rust binary, one Postgres. A small VM or a homelab box runs the whole thing; map serving costs nothing because tiles are static range-requested files, and there is no tile server to scale.