Beacon is a read-mostly public service. The things worth protecting are the admin key, the API listener, your broker and MeshMapper credentials, and the database, which holds decrypted channel messages.
The /api/v1/admin/* endpoints are the only authenticated part of the API. Generate the key
with openssl rand -hex 32, set it as BEACON_API_KEY, and send it only in the
Authorization: Bearer header over HTTPS, never in a URL or a request body. Keep it out of
source control and logs. The rules Beacon enforces (16 characters minimum, no whitespace,
environment wins over the file) are in Configuration.
If you do not need the admin endpoints, do not set a key. They answer 503 and nothing else
changes.
Obtain a regional or grouped-region API key from your local MeshMapper admin and keep it
in MESHMAPPER_API_KEY in the backend environment. Never use the mobile App key, publish
the key through a VITE_* setting, or commit it. Beacon sends it only as X-API-Key to
the supported HTTPS MeshMapper API endpoints and refuses redirects. This is separate
from Beacon's admin authentication. See MeshMapper API key.
beacon-server listens on :8080 with no TLS. In the Docker deployments it is only reachable
from the compose network and from the host's loopback; Caddy is the only thing on a public
port. If you run it another way, bind LISTEN_ADDR to a private address and terminate HTTPS
at the proxy.
Only the page's own host may open /ws unless other origins are listed under
websocket.allowed_origins. REST CORS allows any origin by default but only the read-only
methods (GET, HEAD, OPTIONS). An admin UI on another origin needs cors.allowed_origins
restricted to that UI, the write methods added, and the Authorization and Content-Type
headers allowed, or its preflight requests fail. CORS controls what browsers may do, not who
is authenticated.
REST is limited to 300 requests a minute per client by default, WebSocket upgrades to 10 a
minute, with 5 open sockets per client. Behind a proxy none of that works until
server.trusted_proxies is set; see
Reverse proxy. For repeat offenders, the
fail2ban jails and block list in app_config/fail2ban/
ban at the edge.
Query strings and WebSocket hello payloads are never logged. HTTP completion records carry
the validated client address, route, status and duration. GET /api/v1/admin/config returns
no credentials, broker addresses, channel material or database settings. The backup export,
if you enable it, contains everything the database holds, so keep archives private; see
Backup and export.
.env holds the database password, broker credentials, admin key, and MeshMapper API key. It is gitignored in
the deployment folders; keep it that way, and keep its permissions tight on the host.
data/app/config.yaml holds channel keys. Neither belongs in a public backup.