opentracker.toml.example
⎇
Raw
1# opentracker configuration. Every field can also be set as OT_<UPPERCASE>.
2# Copy to opentracker.toml and edit. All values shown are the defaults.
3
4# HTTP API and web UI. Localhost by default: nginx or Caddy terminates TLS.
5http_addr = "127.0.0.1:7372"
6
7# OTP/1 UDP listener.
8#
9# THE TRAP: HTTP reverse proxies do not forward UDP. This port must be exposed
10# directly by a firewall or NAT rule. If it is not, every phone silently falls
11# back to TLS-over-TCP and you lose the whole point of the protocol.
12udp_addr = "0.0.0.0:7373"
13
14# TLS-over-TCP fallback for UDP-hostile networks. Also needs its own rule.
15# tls_addr = "0.0.0.0:7374"
16
17# What the login response tells phones to connect to. These are the *public*
18# names, which are usually not the same as the bind addresses above.
19public_udp_host = "localhost"
20public_udp_port = 7373
21# public_tls_url = "tls://track.example.com:7374"
22
23base_url = "http://localhost:7372"
24
25# REQUIRED. The OSM tile usage policy demands a contactable User-Agent, and an
26# unidentified tile proxy is blocked without notice. The server refuses to start
27# while this is the placeholder.
28admin_email = "you@example.com"
29
30db_path = "opentracker.db"
31cache_dir = "cache"
32
33# Tile cache ceiling in bytes; eviction runs down to 90% of it. 1 GiB.
34max_cache_bytes = 1073741824
35
36# Point at your own renderer here if you ever run one.
37tile_upstream_url = "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
38
39# Hard drop for points older than this. Points older than 24 h are also thinned
40# to roughly one per 5 minutes. The live marker lives in its own table and is
41# never affected.
42retention_days = 7
43
44# Mark tokens with no activity for this long as revoked. A phone idle for a
45# month has to log in again — the same contract as an expiring browser session.
46#
47# The row and its wrapped key are kept, not deleted. The key is the only thing
48# that can seal a message the phone will believe, and a phone idle for a month is
49# exactly the one that needs telling. A token row is about a hundred bytes.
50token_stale_days = 30
51
52# Accept client timestamps within ±this many days.
53#
54# This is the only server-side handling of a client timestamp anywhere. Nothing
55# corrects a ts, nothing measures clock skew, and no message in the protocol
56# carries the server's clock. This bound exists purely so a phone whose clock says
57# 2106 cannot write rows the retention sweep will never reach.
58ts_window_days = 30
59
60# Answer a datagram naming an unknown token with a sealed REVOKED notice instead
61# of silence, so a phone whose token the server has forgotten lands on the login
62# screen instead of reporting into nothing.
63#
64# THE TRADE: this is the one reply the server sends without having verified the
65# request, which makes the UDP port a reflector — UDP source addresses are
66# forgeable, so the reply goes wherever the sender claimed to be. Three things
67# bound it: the notice is 38 bytes and is refused to any shorter request, so it
68# can never amplify; it is limited to one per destination address per minute
69# under a global ceiling of 10/s; and naming unknown tokens still earns strikes
70# and a ban either way. It cannot be forged, because it is sealed with a key
71# derived from the server master and that token_id.
72#
73# Turning it off costs little. A revoked token keeps its row and its key, so the
74# ordinary "you are logged out" answer is a fully authenticated NACK that never
75# takes this path. This switch only matters when the row is genuinely gone: a
76# restored backup predating the login, or a rotated OT_SECRET_KEY. With it off,
77# those devices get silence until someone opens the app.
78revocation_notices = true
79
80# Argon2id. 19 MiB / 2 passes / 1 lane is OWASP's second recommended profile.
81# Raising these later does not invalidate existing hashes: each hash carries its
82# own parameters and is transparently upgraded on the next successful login.
83argon2_memory_kib = 19456
84argon2_iterations = 2
85argon2_parallelism = 1
86
87# Number of SO_REUSEPORT receive tasks. Defaults to min(cpus, 4).
88# udp_workers = 4
89