7.6 KiB
Troubleshooting
Each heading is a symptom. Under it: the usual cause, then the fix.
docker compose up fails with 403 Forbidden pulling an image
The error looks like ... manifests/<tag>: 403 Forbidden. The GHCR package has been switched,
or defaulted, to private. A maintainer has to set it back to public; the steps are under
Maintainers: publishing images. Nothing on your
side fixes it.
Everyone is getting 429
Beacon rate limits per client IP, and behind a proxy every visitor arrives from the proxy's address unless Beacon is told otherwise. Two things have to be true:
server.trusted_proxiesinconfig.yamllists the proxy's address as a CIDR:/32for one IPv4 host,/128for one IPv6 host,172.30.0.0/24for the all-in-one compose network. A bare address stops startup withfailed to load config ... netip.ParsePrefix("10.0.0.5"): no '/'.- The proxy overwrites
X-Real-IPwith the connecting client's address. The shipped Caddy, nginx and Apache configs do; see Reverse proxy.
Beacon logs a warning at startup when limits are on and no proxy is trusted. The same mistake makes the WebSocket connection cap (5 per IP) hit for everyone at once.
The page loads but nothing is live
The browser could not open the WebSocket. Open the browser's developer tools, Network tab,
filter WS, and look at the /ws request. Causes, most common first:
- The proxy is not passing the upgrade, or sends the upstream address as
Host. nginx needsproxy_http_version 1.1, theUpgradeandConnectionheaders, andproxy_set_header Host $host. - The web app is served from a different host than the API and that origin is not in
websocket.allowed_origins. - The per-IP connection cap is being hit because every visitor looks like the proxy. See the 429 item above.
VITE_WS_URLpoints at the wrong place. It must be the publicwss://address, notlocalhost.
Caddy never gets a certificate
docker compose logs caddy shows ACME errors. Either DNS for DOMAIN is not pointing at this
server yet, or ports 80 and 443 are not reachable from the internet. Fix that and Caddy
retries on its own.
Startup fails with database schema predates Beacon 2.0.0
The database was created by Beacon 1.x. 2.0.0 cannot migrate it. Move the old data directory aside and start with an empty one; see Upgrading.
Startup fails on a config value
Beacon refuses to run with a setting it cannot honour. The message names the key:
| Message | Fix |
|---|---|
scope "x" needs a region |
Add region: <slug> to that scopes: entry. |
scope "x" region "y" is not a configured region |
Use a slug that appears under regions:. |
netip.ParsePrefix("10.0.0.5"): no '/' |
Write 10.0.0.5/32, not 10.0.0.5. An empty entry fails with server.trusted_proxies[0] must be a valid CIDR instead. |
packets.retention must be at least 24h |
Raise it. Same for analytics.rollup_retention. |
meshmapper.scopes.refresh_interval must be between 1h and 24h |
Set it inside that range. Repeaters is also 1h to 24h; zones and channels intervals are 24h to 168h. |
nodes.mark_foreign requires an iatas.*.borderFile or meshmapper.zones |
Add a border source or turn mark_foreign off. |
not a well-formed GeoJSON Feature, ring 0 is not closed, geometry must be Polygon or MultiPolygon |
The border file is invalid. It must be a single GeoJSON Feature with a closed Polygon or MultiPolygon in longitude, latitude order. |
log level must be debug, info, warn or error |
Check log.level and LOG_LEVEL. log format must be text or json is the same for format. |
auth.api_key / BEACON_API_KEY must be at least 16 characters |
Use a longer key, with no whitespace inside it. |
No packets are arriving
Check GET /api/v1/brokers first.
- A broker shows disconnected.
MQTT_BROKER_1_URLmust be the WebSocket endpoint, usuallywss://host:443, and the username and password must be a subscriber account on that broker.docker compose logs appshows the connect error. See Getting packets in. - Connected but nothing stored. No observers are publishing to that broker, or
ingest.allow_countries/allow_continentsinconfig.yamlis filtering them out.GET /api/v1/observersshows who Beacon has heard from. - Packets arrive but with no signal data. The account is Role 3, which strips
snrandrssi. Ask for a Role 2 account.
Every path hop says "confidence": "none"
Path resolution needs to know which nodes exist, and Beacon learns that from adverts. On a
fresh database every hop is none and supportsMultibytePaths is false until nodes have
advertised. This fills in on its own as the mesh is observed.
Channel messages show a hash but no text
The channel's key is not configured, or it was added without a restart. Add it under
channel_keys: in config.yaml and run docker compose restart app. On start, Beacon decrypts
the stored messages for the new key and logs
config: backfilled N previously-undecrypted channel message(s).
MeshMapper imports are unconfigured or stale
Read docker compose logs app for component=meshmapper, meshmapper.zones,
meshmapper.scopes, meshmapper.channels, or meshmapper.repeaters. Refresh records include last_error,
next_attempt, and, for regional imports, checked_at.
| Message | Fix |
|---|---|
unconfigured: MeshMapper API key is missing |
Set MESHMAPPER_API_KEY in the backend environment. An explicitly empty environment value overrides a YAML key. |
unconfigured: MeshMapper API key contains invalid characters |
Re-enter the key supplied by your local MeshMapper regional or grouped-region admin; remove embedded whitespace or control characters. |
authentication failed (HTTP 401) |
Check that you are using the correct regional or grouped-region API key and that MeshMapper Server supports X-API-Key. Do not use the mobile App key. |
permission denied (HTTP 403) |
Ask the MeshMapper admin to check access to the requested API and IATA. A group key needs every member IATA, including members added by import_groups. |
HTTP 429 or HTTP 503 |
Wait until next_attempt. Beacon honours longer Retry-After delays and its existing refresh limits. Do not shorten polling intervals or repeatedly restart to force a request. |
After changing .env, run docker compose up -d --force-recreate app from the backend
deployment folder. A plain restart does not reload container environment variables.
Persisted backoff still applies after a restart. Never paste the key into logs, URLs, or
support messages.
Beacon keeps the last successful cached data and freshness timestamp after a failed refresh, including an authentication failure. It does not replace imports with empty lists or retry anonymously. See MeshMapper API key for setup and rollout requirements.
Backup export refuses a saved MeshMapper key
Move the key from meshmapper.api_key to MESHMAPPER_API_KEY in the backend environment,
clear the saved YAML value, and recreate app. Backups include saved YAML verbatim, so
exports refuse a nonempty MeshMapper key there to keep it out of download responses.
See Backup and export.
I changed a VITE_* value and nothing changed
Run docker compose up -d web (docker compose up -d beacon-web in the split deployment). The web container writes the values to /config.js when it
starts, so an edited .env does nothing until the container is recreated. Then hard-refresh
the page.