# opentracker Self-hosted location sharing. Devices upload positions over HTTPS. A web map shows your position and the positions others share with you. ![The web map with a person's trail](docs/screenshots/web.webp) ``` crates/api JSON types shared by server and web crates/server otserver: axum + SQLite, serves the API and web/dist web/ Leptos + Leaflet, built with Trunk android/ Android app: background tracking, this device's map, see android/README.md ``` ## Deployment Set `OT_PUBLIC_URL` in `compose.yaml` to your address. Then start the server: ```sh docker compose up -d ``` The container listens on `127.0.0.1:8080`. Put a TLS reverse proxy in front of it. A proxy with HTTP/3 is recommended, because phones reconnect faster after sleep. The Android app uses HTTP/3 from Android 14. Caddy does HTTP/3 by default: ``` track.example.com { encode zstd gzip reverse_proxy 127.0.0.1:8080 } ``` HTTP/3 needs UDP 443 open next to TCP 443. Open the address and create the admin account. The first visitor gets this account, so do it before you expose the server. The server updates the database schema at start. Back up the database file before you upgrade. ### Reverse proxy - `--public-url` is the address that browsers use. Passkeys are bound to it. An `https://` URL also marks the session cookie `Secure`. - `--trusted-proxy` makes the sign-in rate limits use the client address from the proxy's `X-Forwarded-For` header. Only turn it on when clients cannot reach the server port directly. Otherwise they can fake the header. `compose.yaml` sets both. ## Configuration Every flag can also be set by its environment variable. `otserver --help` lists them. | Flag | Variable | Default | | |---|---|---|---| | `--addr` | `OT_ADDR` | `127.0.0.1:8080` | listen address | | `--db` | `OT_DB` | `ot.db` | SQLite file | | `--web-dir` | `OT_WEB_DIR` | `web/dist` | built web UI | | `--public-url` | `OT_PUBLIC_URL` | | the address browsers use, see [Reverse proxy](#reverse-proxy) | | `--retention-days` | `OT_RETENTION_DAYS` | `30` | days to keep points, `0` keeps them forever. Users can choose a shorter time. | | `--trusted-proxy` | `OT_TRUSTED_PROXY` | off | trust `X-Forwarded-For`, see [Reverse proxy](#reverse-proxy) | `otserver passwd ` creates a user or resets a password. A reset also removes the user's passkeys and device tokens. ## Usage - Admins manage users under Settings → Users. - Each user can sign in with a password, a passkey, or both (two-factor). Choose this under Settings → Security. - Devices sign in with a token. The Android app gets one through the browser. For other clients, create one under Settings → Devices. - A person can upload from several devices. The map shows one dot per person, at the newest position. - A share with another user chooses which devices, how much history and how exact the position is. - A guest link shares with anyone who has the link, optionally with a password. ## Development ```sh cd web && trunk build && cd .. # or `trunk serve`: live reload on :8081, API proxied to :8080 cargo run -p server # http://localhost:8080 ``` Send a point as a device: ```sh URL=http://localhost:8080 TOKEN=... # a token from Settings → Devices curl -H "Authorization: Bearer $TOKEN" --json "[{\"ts\":$(date +%s),\"lat\":48.137,\"lon\":11.575}]" $URL/api/points ``` ### Android app See [android/README.md](android/README.md). ### Languages The web UI and the app are in English and German. Web texts live in `web/src/i18n.rs`. App texts live in `android/app/src/main/res/values*/strings.xml`.