ADSB2MQTT shares local ADS-B receiver data over MQTT to build a collaborative aircraft network.
500
ADSB2MQTT is an open source platform for sharing ADS-B readings from local receivers over MQTT and building a collaborative real-time aircraft network.
The project exists to make locally captured ADS-B data easier to share and to reward contributors with simple access to aggregated data from the rest of the network. Every node that contributes data should be able to consume data from other contributing nodes.
dump1090, readsb, tar1090, or similar stacks.aircraft.json-compatible API.dump1090 ecosystem.graph TD;
antenna["Antenna / SDR"] --> dump1090["dump1090 / readsb"];
dump1090 --> node["adsb2mqtt-node"];
node --> publicLocalhost;
subgraph publicLocalhost[" "]
direction LR
public["Public"] <--> localhost["Localhost"];
end
localhost --> localApi["Local API /v1/aircraft"];
localhost --> localMqtt["Local MQTT"];
sequenceDiagram
participant Antenna as Antenna / SDR
participant Dump1090 as dump1090 / readsb
participant Node as adsb2mqtt-node
participant Local as Localhost
participant Server as adsb2mqtt-server
participant Public as Public MQTT Seed
Node->>Server: registers or validates ADSBDB_NODE_ID
Server-->>Node: returns ADSBDB_NODE_ID, ADSBDB_TOKEN, and MQTT credentials
Server->>Public: syncs node ACL and password
Antenna->>Dump1090: receives ADS-B / Mode-S signals
Dump1090-->>Node: sends Beast or aircraft.json
par Public publishing
Node->>Public: publishes adsbdb/raw/<node_id>
Node->>Public: publishes adsbdb/aircraft/<node_id>/<hex>
Public-->>Server: delivers messages from nodes
Server-->>Public: makes aggregated network data available
and Local consumption
Node->>Local: exposes local API /v1/aircraft
Node->>Local: exposes optional local MQTT
end
alt Public seed unavailable
Node-->>Public: keeps reconnecting
Node->>Local: keeps local API and local MQTT available
end
The node publishes ADS-B/Mode-S messages to the public MQTT network while, in parallel, it can expose local consumption through a dump1090 aircraft.json compatible API and optional local MQTT. If the public seed is unavailable, the node keeps trying to reconnect automatically while the local API and local MQTT keep working for consumers on the same machine or local network.
If you already have Beast output available, run the node:
docker run -d \
--name adsb2mqtt-node \
--restart unless-stopped \
-e BEASTHOST="YOUR_DUMP1090_IP" \
-e BEASTPORT="YOUR_DUMP1090_PORT" \
lcaloi/adsb2mqtt-node:latest
On first boot, if ADSBDB_NODE_ID and ADSBDB_TOKEN are not declared, the node registers a network identity and prints setup instructions in the container logs:
ADS-B DB NODE REGISTERED
ADSBDB_NODE_ID
uuid-issued-by-the-network
ADSBDB_TOKEN
token-issued-by-the-network
Persist both values in your .env or docker-compose.yml to keep the same identity when the container is recreated.
curl http://localhost/v1/aircraft
{
"now": 1785973864,
"messages": 547355,
"aircraft": [
{
"hex": "e49e6c",
"type": "adsb_icao",
"flight": "PTLLG ",
"alt_baro": 12000,
"gs": 232.8,
"track": 319.88,
"lat": -21.157562,
"lon": -49.430886,
"seen": 0.9,
"rssi": -26.8
}
]
}
Local endpoints:
curl http://localhost:8080/healthz
curl http://localhost:8080/v1/aircraft
curl http://localhost:8080/v1/nodes/ranking
curl http://localhost:8081/v1/aircraft
aircraft.json.Common dump1090/readsb ports:
| Port | Common use |
|---|---|
30002 | Raw output |
30003 | SBS/BaseStation |
30005 | Beast output |
30008 | Beast/receiver output in some setups |
docker run -d \
--name adsb2mqtt-node \
--restart unless-stopped \
-e BEASTHOST="192.168.68.103" \
-e BEASTPORT="30005" \
lcaloi/adsb2mqtt-node:latest
Built-in defaults:
ADSBDB_POLL_INTERVAL=5s
ADSBDB_MAX_BATCH=200
services:
node:
image: lcaloi/adsb2mqtt-node:latest
restart: unless-stopped
environment:
BEASTHOST: "127.0.0.1"
BEASTPORT: "30005"
ADSBDB_NODE_ID: ""
ADSBDB_TOKEN: ""
After the first registration, fill ADSBDB_NODE_ID and ADSBDB_TOKEN with the values printed in the logs.
When ADSBDB_NODE_ID is not declared, the node automatically registers a new identity:
adsb2mqtt-node -> POST /v1/nodes/register -> adsb2mqtt-server
The server generates:
node_id: UUID v4 issued by the network.token: secret used to authenticate the node.On first registration, the log shows:
============================================
ADS-B DB NODE REGISTERED
--------------------------------------------
Persist this network identity before
recreating the container.
ADSBDB_NODE_ID
5fd61d1c-37aa-4c77-8bd0-f27550cfe06f
ADSBDB_TOKEN
secret
Add both values to docker-compose.yml
or to your .env file.
============================================
If ADSBDB_NODE_ID is already declared, the node reuses that identity and the server validates whether the ADSBDB_NODE_ID + ADSBDB_TOKEN pair was issued by the network. A random ID receives 401 Unauthorized.
Beast mode:
BEASTHOST=127.0.0.1
BEASTPORT=30005
Enriched mode with aircraft.json:
DUMP1090_URL=http://127.0.0.1/data/aircraft.json
When BEASTHOST and DUMP1090_URL are configured together, the node uses Beast for real-time contribution and queries the dump1090 JSON to enrich /v1/aircraft with fields already calculated by the receiver.
If only Beast is configured, the node/server attempts to decode fields such as type, flight, alt_baro, gs, track, baro_rate, lat, and lon. Position decoding depends on recent even/odd CPR pairs from the same aircraft.
The node publishes to the central broker:
adsbdb/raw/<node_id>
adsbdb/aircraft/<node_id>/<hex>
adsbdb/status/<node_id>
When MQTT connects, the expected log is:
connected to mqtt url=mqtt://seed.adsbdb.com.br:4222
published mqtt raw_messages=200 ...
If the public MQTT seed goes down, the node retries every 60 seconds. It does not use HTTP fallback for ingest while MQTT is configured; it keeps the local store and waits for reconnection:
mqtt unavailable raw_messages=200 ... waiting_reconnect=true
retrying mqtt connection url=mqtt://seed.adsbdb.com.br:4222
The adsb2mqtt-node image can start a local Mosquitto broker inside the same container for local consumers.
Enable it with:
ADSBDB_EMBEDDED_MQTT=true
ADSBDB_NODE_MQTT_PORT=1883
By default, the embedded local broker starts without login when these variables are empty:
ADSBDB_MQTT_ADMIN_USERNAME=
ADSBDB_MQTT_ADMIN_PASSWORD=
To require authentication on the local broker, set both:
ADSBDB_MQTT_ADMIN_USERNAME=admin
ADSBDB_MQTT_ADMIN_PASSWORD=abc123
If only one of them is set, the container fails on startup to avoid ambiguous configuration.
When embedded MQTT is enabled, the local Mosquitto bridges to the official public seed:
ADSBDB_EMBEDDED_MQTT=true
In this mode, the node publishes to the local broker at mqtt://127.0.0.1:1883, and local Mosquitto replicates to mqtt://seed.adsbdb.com.br:4222.
The bridge is bidirectional by topic:
local -> official seed:
adsbdb/raw/<node_id>
adsbdb/aircraft/<node_id>/+
adsbdb/status/<node_id>
official seed -> local:
adsbdb/raw/+
adsbdb/aircraft/+/+
The bridge uses the node MQTT credentials for the official seed. On first boot, adsb2mqtt-node registers the identity first, receives ADSBDB_NODE_ID and ADSBDB_TOKEN, and only then starts local Mosquitto with the authenticated bridge. There is no need to restart the container just to activate the bridge after first onboarding.
The node exposes a local API on :8081:
curl http://localhost:8081/healthz
curl http://localhost:8081/v1/aircraft
curl http://localhost:8081/v1/stats
| Variable | Default | Description |
|---|---|---|
ADSBDB_NODE_ID | empty | Public node identifier. If empty, the node requests a UUID from the network. |
ADSBDB_TOKEN | empty | Token used to authenticate when ADSBDB_NODE_ID is already declared. |
ADSBDB_MQTT_USERNAME | node_<ADSBDB_NODE_ID> | Node MQTT username. |
ADSBDB_MQTT_PASSWORD | ADSBDB_TOKEN | Node MQTT password. |
ADSBDB_NODE_ADDR | :8081 | Local HTTP address for the node. |
BEASTHOST | empty | Beast output host/IP. |
BEASTPORT | 30008 | Beast TCP port. |
DUMP1090_URL | empty | URL for dump1090/readsb aircraft.json. |
ADSBDB_POLL_INTERVAL | 5s | Batch send interval. |
ADSBDB_MAX_BATCH | 200 | Maximum messages per batch. |
ADSBDB_EMBEDDED_MQTT | false | Starts local Mosquitto inside the container. |
ADSBDB_MQTT_ADMIN_USERNAME | empty | Local broker admin user. If username and password are empty, local MQTT starts without login. |
ADSBDB_MQTT_ADMIN_PASSWORD | empty | Local broker admin password. Must be set together with the username to require authentication. |
Check whether the receiver is reachable from the machine running Docker:
ping 192.168.68.103
nc -vz 192.168.68.103 30005
Test the central MQTT broker:
nc -vz seed.adsbdb.com.br 4222
Subscribe to topics:
mosquitto_sub -h seed.adsbdb.com.br -p 4222 \
-u ADSBDB_NODE_ID -P ADSBDB_TOKEN \
-t 'adsbdb/#' -v
Important logs:
published mqtt raw_messages=... # MQTT active
sent raw_messages=... # HTTP fallback, only when MQTT is empty
mqtt unavailable ... # MQTT configured, waiting for reconnection
mqtt connect timeout ... # broker unreachable on startup
dump1090 aircraft.json compatible output.ADSBDB_DEPRECATED_JOIN_TOKENS.MIT. See LICENSE.
Content type
Image
Digest
sha256:4dfcf505d…
Size
8.9 MB
Last updated
about 1 hour ago
docker pull lcaloi/adsb2mqtt-node