Self-host the family GPS tracker on a server you trust.
The quick start is enough for a laptop. Use this checklist before you invite a family onto a VPS or NAS that is reachable from the internet. It restates docs/self-hosting.md — it does not invent a different architecture.
Before docker compose up
- Copy
.env.exampleto.env. Do not commit.env. - Set
APP_ENV=production. - Set
JWT_SECRETto at least 32 random bytes (openssl rand -base64 48). - Set
POSTGRES_PASSWORD(andDATABASE_URLwithsslmode=requireif Postgres is not on the Compose network). - Set
SITE_ADDRESS=openfamily.example.com(Caddy will request a certificate). - Set
PLATFORM_ADMIN_EMAILandPLATFORM_ADMIN_PASSWORD. This creates the first admin and closes open registration (invite codes required). - Set
TLS_BEHIND_PROXY=true(Compose default) so the API accepts HTTP from Caddy on the private network.
Step 5 in detail — DNS records, certificate behavior, and troubleshooting — is covered in custom-domain.md. The admin panel's Settings → Custom domain card runs live DNS and HTTPS checks against your setup.
Android push (ntfy)
Do not publish ntfy on 0.0.0.0:2586. Current Compose binds loopback only.
For phones on the public internet:
PUSH_ADDRESS=push.example.com
NTFY_BASE_URL=https://push.example.com
CADDYFILE=Caddyfile.with-push
Install the ntfy Android app on each phone. UnifiedPush registration is silent; if alerts never arrive, ntfy is usually missing.
Map tiles
Default street tiles are public OSM; satellite is Esri. Those hosts see the viewport. To use another raster provider (API key goes in the URL):
TILE_URL=https://tiles.example.com/{z}/{x}/{y}.png?api_key=xxx
SATELLITE_TILE_URL=
The API returns these on GET /config. The generic APK does not need a rebuild. A key in TILE_URL is visible to every phone.
Optional SMS
Set TWILIO_* and PUBLIC_BASE_URL=https://openfamily.example.com so SOS messages carry a share link instead of raw coordinates. The same values can be saved on the admin Settings page; a saved row overrides empty env values without restarting. Emergency contacts appear in the app only when SMS is configured.
Backups and disk encryption
- Volume
pgdatais the family database. Snapshot it. Schedulepg_dump. - Enable host disk encryption (LUKS, Synology volume encryption, cloud disk encryption). The app does not encrypt rows itself.
- Keep
app/android/upload-keystore.jks(or CI signing secrets) backed up. Losing the keystore forces every phone to uninstall before they can update.
Custom domain
Serving OpenFamily behind a real domain gives every device automatic HTTPS: Caddy requests and renews a Let's Encrypt certificate. Create an A (and optional AAAA) record for the name, forward ports 80 and 443 if you are behind a home router, then set:
SITE_ADDRESS=openfamily.example.com
ALLOWED_ORIGIN=https://openfamily.example.com
PUBLIC_BASE_URL=https://openfamily.example.com
APP_ENV=production
Then docker compose up -d. Point the apps at https://your-domain. Full DNS and NAT-loopback notes: docs/custom-domain.md.
Family setup
- Install the Android APK from the admin Builds page (or the GitHub Release).
- Enter
https://openfamily.example.comand Connect. - Create an account (invite code if the server requires one).
- Allow Always location, notifications, and the battery exemption.
- Install ntfy so alerts arrive when the app is closed.
More operator detail lives in the canonical README. Privacy boundaries: privacy.