mirror of
https://github.com/MeshCore-Beacon/beacon-docs.git
synced 2026-10-23 01:51:24 +00:00
64 lines
3.2 KiB
Markdown
64 lines
3.2 KiB
Markdown
# Securing a deployment
|
|
|
|
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 admin key
|
|
|
|
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](configuration.md#admin-api-key).
|
|
|
|
If you do not need the admin endpoints, do not set a key. They answer `503` and nothing else
|
|
changes.
|
|
|
|
## The MeshMapper API key
|
|
|
|
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](configuration.md#meshmapper-api-key).
|
|
|
|
## Keep the API listener private
|
|
|
|
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.
|
|
|
|
## Browser origins
|
|
|
|
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.
|
|
|
|
## Rate limits and bans
|
|
|
|
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](reverse-proxy.md#rate-limits-and-connection-caps). For repeat offenders, the
|
|
fail2ban jails and block list in [`app_config/fail2ban/`](../app_config/fail2ban/README.md)
|
|
ban at the edge.
|
|
|
|
## What Beacon logs and returns
|
|
|
|
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](backup-export.md).
|
|
|
|
## Secrets in files
|
|
|
|
`.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.
|