Containerized dump978 for decoding 978 MHz UAT ADS-B with RTL-SDR or SoapySDR on Linux.
Sponsored and maintained by Blackout Secure.
Important
This repository is not an official LinuxServer.io image release.
This project packages upstream flightaware/dump978 into a containerized build for decoding 978 MHz UAT ADS-B with RTL-SDR or SoapySDR on Linux.
Quick links:
- Docker Hub listing: blackoutsecure/dump978
- Balena block listing: dump978 block on Balena Hub
- GitHub repository: blackoutsecure/docker-dump978
- Upstream application: flightaware/dump978
- docker-dump978
docker run -d \
--name=dump978 \
--restart unless-stopped \
-e TZ=Etc/UTC \
-e DUMP978_SDR=driver=rtlsdr \
-e DUMP978_LAT=47.6062 \
-e DUMP978_LON=-122.3321 \
-p 8978:8978 \
-p 30978:30978 \
-p 30979:30979 \
-v dump978-config:/config \
-v /run/dump978-fa:/run/dump978-fa \
--device /dev/bus/usb:/dev/bus/usb \
blackoutsecure/dump978:latestAccess the SkyAware978 web UI at http://<host-ip>:8978/.
For compose files, balena, and more examples, see Usage below.
Docker Hub (Recommended):
- All images published to Docker Hub
- Simple pull command:
docker pull blackoutsecure/dump978:latest - Multi-arch support: amd64, arm64
- No registry prefix needed (defaults to Docker Hub)
# Pull latest
docker pull blackoutsecure/dump978
# Pull specific version
docker pull blackoutsecure/dump978:10.2
# Pull architecture-specific (rarely needed)
docker pull blackoutsecure/dump978:latest@amd64dump978-fa is FlightAware's 978 MHz UAT (Universal Access Transceiver) decoder. It demodulates UAT signals from an RTL-SDR or other SoapySDR-compatible receiver and provides decoded ADS-B data as raw messages or JSON-formatted output on network ports. The companion skyaware978 writes JSON files suitable for the SkyAware web map.
Author and maintenance credits (upstream):
- Primary upstream maintainer: FlightAware
- Original implementation: mutability/dump978
- Upstream repository and documentation: flightaware/dump978
This image is published as a multi-arch manifest. Pulling blackoutsecure/dump978:latest retrieves the correct image for your host architecture.
The architectures supported by this image are:
| Architecture | Tag |
|---|---|
| x86-64 | amd64-latest |
| arm64 | arm64v8-latest |
docker-compose (recommended, click here for more info)
---
services:
dump978:
image: blackoutsecure/dump978:latest
container_name: dump978
environment:
- TZ=Etc/UTC
- DUMP978_SDR=driver=rtlsdr
volumes:
- config:/config
- dump978-run:/run/dump978-fa
ports:
- 8978:8978 # SkyAware978 Web UI (HTTP)
- 30978:30978 # Raw UAT messages
- 30979:30979 # Decoded JSON messages
devices:
- /dev/bus/usb:/dev/bus/usb
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETUID
- SETGID
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp
- /run:exec
restart: unless-stopped
volumes:
config:
dump978-run:---
services:
readsb:
image: blackoutsecure/readsb:latest
container_name: readsb
environment:
- TZ=Etc/UTC
volumes:
- readsb-config:/config
- readsb-run:/run/readsb
devices:
- /dev/bus/usb:/dev/bus/usb
tmpfs:
- /tmp
- /run:exec
restart: unless-stopped
dump978:
image: blackoutsecure/dump978:latest
container_name: dump978
environment:
- TZ=Etc/UTC
- DUMP978_SDR=driver=rtlsdr
volumes:
- dump978-config:/config
- dump978-run:/run/dump978-fa
ports:
- 8978:8978
- 30978:30978
- 30979:30979
devices:
- /dev/bus/usb:/dev/bus/usb
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETUID
- SETGID
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp
- /run:exec
restart: unless-stopped
volumes:
readsb-config:
readsb-run:
dump978-config:
dump978-run:docker-cli (click here for more info)
docker run -d \
--name=dump978 \
-e TZ=Etc/UTC \
-e DUMP978_SDR=driver=rtlsdr \
-p 8978:8978 \
-p 30978:30978 \
-p 30979:30979 \
-v /path/to/dump978/config:/config \
-v /run/dump978-fa:/run/dump978-fa \
--device /dev/bus/usb:/dev/bus/usb \
--restart unless-stopped \
blackoutsecure/dump978:latestThis image can be deployed to Balena-powered IoT devices using the included docker-compose.yml file (which contains the required Balena labels):
- Balena block listing: https://hub.balena.io/blocks/dump978
balena push <your-app-slug>For deployment via the web interface, use the deploy button in this repository. See Balena documentation for details.
| Parameter | Function |
|---|---|
-p 8978:8978 |
SkyAware978 Web UI (HTTP) |
-p 30978:30978 |
Raw UAT messages |
-p 30979:30979 |
Decoded JSON messages |
| Parameter | Function | Required |
|---|---|---|
-e DUMP978_PROFILE=adsbexchange |
Feed profile: flightaware or adsbexchange. Controls default branding, feeder behavior, and TIS-B filtering. See Feed Profiles. |
Optional |
-e DUMP978_TISB_FILTER= |
Filter out TIS-B traffic. Default depends on profile: false for flightaware, true for adsbexchange. |
Optional |
-e DUMP978_ENABLE_FAUP978= |
Enable faup978 FlightAware reporter. Default depends on profile: true for flightaware, false for adsbexchange. |
Optional |
| Parameter | Function | Required |
|---|---|---|
-e TZ=Etc/UTC |
Timezone (TZ database) | Optional |
-e DUMP978_SDR=driver=rtlsdr |
SoapySDR device string for the SDR receiver | Optional |
-e DUMP978_SDR_GAIN= |
Manual SDR gain setting (overrides auto-gain if set) | Optional |
-e DUMP978_SDR_AUTO_GAIN=true |
Enable automatic gain control (true/false) |
Optional |
-e DUMP978_RAW_PORT=30978 |
TCP port for raw UAT messages | Optional |
-e DUMP978_JSON_PORT=30979 |
TCP port for decoded JSON messages | Optional |
-e DUMP978_EXTRA_ARGS= |
Additional arguments passed to dump978-fa | Optional |
-e DUMP978_WEB_PORT=8978 |
HTTP port for the SkyAware978 web UI | Optional |
-e DUMP978_USER=abc |
Runtime user | Optional |
-e PUID=911 |
User ID for file ownership | Optional |
-e PGID=911 |
Group ID for file ownership | Optional |
| Parameter | Function | Required |
|---|---|---|
-e DUMP978_SDR_PPM= |
Frequency correction in PPM (critical for many RTL-SDR dongles) | Optional |
-e DUMP978_SDR_ANTENNA= |
SDR antenna name (for multi-antenna devices) | Optional |
-e DUMP978_SDR_DEVICE_SETTINGS= |
SoapySDR device key-value settings | Optional |
-e DUMP978_SDR_STREAM_SETTINGS= |
SoapySDR stream key-value settings | Optional |
-e DUMP978_FORMAT= |
Sample format: CU8, CS8, CS16H, CF32H |
Optional |
-e DUMP978_RAW_LEGACY_PORT= |
TCP port for raw messages without metadata header (legacy clients) | Optional |
-e DUMP978_STRATUX= |
Stratux v3 serial device path (e.g. /dev/ttyUSB0); replaces SDR input |
Optional |
| Parameter | Function | Required |
|---|---|---|
-e DUMP978_LAT= |
Receiver latitude (e.g. 47.6062) — enables site marker and range rings |
Optional |
-e DUMP978_LON= |
Receiver longitude (e.g. -122.3321) — enables site marker and range rings |
Optional |
-e DUMP978_AUTO_LOCATION=true |
Auto-detect location via IP geolocation when LAT/LON not set | Optional |
-e DUMP978_FA_STATS_URL= |
FlightAware stats page URL (e.g. https://flightaware.com/adsb/stats/user/yourname). Used when profile is flightaware. |
Optional |
-e DUMP978_ADSBX_STATS_URL= |
ADS-B Exchange stats page URL (e.g. https://www.adsbexchange.com/myip/). Used when profile is adsbexchange. |
Optional |
-e DUMP978_STATS_URL= |
Generic stats URL fallback — used if the profile-specific URL above is empty | Optional |
| Parameter | Function | Required |
|---|---|---|
-e DUMP978_ENABLE_FAUP978= |
Enable faup978 FlightAware UAT data reporter (true/false). Default depends on profile. |
Optional |
-e FAUP978_CONNECT= |
Override host:port to connect to (default: localhost:30978) |
Optional |
| Parameter | Function | Required |
|---|---|---|
-e SKYAWARE978_RECONNECT_INTERVAL=30 |
Seconds to wait before reconnecting on connection failure | Optional |
-e SKYAWARE978_HISTORY_COUNT=120 |
Number of history JSON files to maintain | Optional |
-e SKYAWARE978_HISTORY_INTERVAL=30 |
Seconds between history file captures | Optional |
-e SKYAWARE978_CONNECT= |
Override host:port to connect to (default: localhost:30978) |
Optional |
-e SKYAWARE978_WRITE_DIR= |
Override JSON output directory (default: /run/skyaware978) |
Optional |
-e SKYAWARE978_EXTRA_ARGS= |
Additional arguments passed to skyaware978 | Optional |
Settings can be configured via environment variables, or by placing a complete custom config.js file at /config/skyaware978-config.js (takes priority over env vars). The active feed profile sets default values for SKYAWARE_PAGE_NAME and SKYAWARE_SITE_NAME; explicit env vars override them.
| Parameter | Function | Required |
|---|---|---|
-e SKYAWARE_PAGE_NAME= |
Browser title and page header. Default: SkyAware978 (FlightAware) or ADS-B Exchange UAT (ADSBx) |
Optional |
-e SKYAWARE_SITE_NAME= |
Tooltip text for the site marker. Default: FlightAware UAT or ADS-B Exchange |
Optional |
-e SKYAWARE_DISPLAY_UNITS= |
Default units: nautical, metric, or imperial |
Optional |
-e SKYAWARE_DEFAULT_CENTER_LAT= |
Default map center latitude | Optional |
-e SKYAWARE_DEFAULT_CENTER_LON= |
Default map center longitude | Optional |
-e SKYAWARE_DEFAULT_ZOOM= |
Default map zoom level (0–16) | Optional |
-e SKYAWARE_SITE_CIRCLES= |
Show range rings (true/false) |
Optional |
-e SKYAWARE_SITE_CIRCLES_COUNT= |
Number of range rings (default: 3) |
Optional |
-e SKYAWARE_SITE_CIRCLES_BASE= |
Base distance for first ring | Optional |
-e SKYAWARE_SITE_CIRCLES_INTERVAL= |
Distance between rings | Optional |
-e SKYAWARE_SHOW_FLAGS= |
Show country flags (true/false) |
Optional |
-e SKYAWARE_CHARTBUNDLE= |
Enable ChartBundle US sectional chart layers (true/false) |
Optional |
-e SKYAWARE_BING_API_KEY= |
Bing Maps API key for satellite imagery | Optional |
-e SKYAWARE_EXTENDED_DATA= |
Show extended Mode S EHS / ADS-B v2 data (true/false) |
Optional |
-e SKYAWARE_PLANE_COUNT_IN_TITLE= |
Show aircraft count in page title (true/false) |
Optional |
-e SKYAWARE_MSG_RATE_IN_TITLE= |
Show message rate in page title (true/false) |
Optional |
| Parameter | Function | Required |
|---|---|---|
-v /config |
Persistent configuration | Recommended |
-v /run/dump978-fa |
Decoder output directory | Recommended |
The container uses two volumes:
- Purpose: Stores persistent configuration files (
dump978-fa,skyaware978) - Example:
-v /path/to/dump978/config:/configor-v dump978-config:/config
- Purpose: Runtime output directory for dump978-fa data accessible by other containers
- Example:
-v /run/dump978-fa:/run/dump978-faor-v dump978-run:/run/dump978-fa
Environment variables are set using -e flags in docker run or the environment: section in docker-compose.
Configuration files are stored in /config inside the container. On first run, default configuration files are created at /config/dump978-fa and /config/skyaware978.
Set DUMP978_PROFILE to switch between preconfigured defaults for different ADS-B networks. The profile controls branding, feeder behavior, and filtering — every default can still be overridden with explicit env vars.
flightaware |
adsbexchange (default) |
|
|---|---|---|
| Web UI page name | SkyAware978 | ADS-B Exchange UAT |
| Site name | FlightAware UAT | ADS-B Exchange |
| faup978 feeder | Enabled | Disabled |
| TIS-B filtering | Off (false) |
On (true) |
| Stats URL source | DUMP978_FA_STATS_URL |
DUMP978_ADSBX_STATS_URL |
| status.json radio type | dump978-fa |
dump978-fa (ADS-B Exchange) |
Example — switch to FlightAware profile:
environment:
DUMP978_PROFILE: "flightaware"
DUMP978_FA_STATS_URL: "https://flightaware.com/adsb/stats/user/yourname"Example — ADS-B Exchange profile (default):
environment:
DUMP978_PROFILE: "adsbexchange"
DUMP978_ADSBX_STATS_URL: "https://www.adsbexchange.com/myip/"You can set both stats URLs and switch profiles at will — only the active profile's URL is used.
| Variable | Default | Description |
|---|---|---|
DUMP978_SDR |
driver=rtlsdr |
SoapySDR device string |
DUMP978_SDR_GAIN |
(blank) | Manual SDR gain setting (overrides auto-gain if set) |
DUMP978_SDR_AUTO_GAIN |
true |
Enable automatic gain control |
DUMP978_SDR_PPM |
(blank) | Frequency correction in PPM |
DUMP978_SDR_ANTENNA |
(blank) | SDR antenna name |
DUMP978_SDR_DEVICE_SETTINGS |
(blank) | SoapySDR device key-value settings |
DUMP978_SDR_STREAM_SETTINGS |
(blank) | SoapySDR stream key-value settings |
DUMP978_FORMAT |
(auto-detect) | Sample format: CU8, CS8, CS16H, CF32H |
DUMP978_STRATUX |
(blank) | Stratux v3 serial device (replaces SDR input) |
DUMP978_RAW_PORT |
30978 |
TCP port for raw UAT messages |
DUMP978_JSON_PORT |
30979 |
TCP port for decoded JSON messages |
DUMP978_RAW_LEGACY_PORT |
(blank) | TCP port for raw messages without metadata header |
DUMP978_EXTRA_ARGS |
(blank) | Additional dump978-fa command-line arguments |
To select a specific RTL-SDR dongle by serial number: DUMP978_SDR=driver=rtlsdr,serial=01234567
| Variable | Default | Description |
|---|---|---|
SKYAWARE978_CONNECT |
localhost:30978 |
dump978-fa raw port to connect to |
SKYAWARE978_WRITE_DIR |
/run/skyaware978 |
Directory for JSON output files |
SKYAWARE978_RECONNECT_INTERVAL |
30 |
Seconds to wait before reconnecting on failure |
SKYAWARE978_HISTORY_COUNT |
120 |
Number of history JSON files to maintain |
SKYAWARE978_HISTORY_INTERVAL |
30 |
Seconds between history file captures |
SKYAWARE978_EXTRA_ARGS |
(blank) | Additional skyaware978 command-line arguments |
The faup978 binary re-encodes UAT messages into FlightAware's format for stats collection. It is enabled by default with the flightaware profile and disabled by default with the adsbexchange profile. Override with DUMP978_ENABLE_FAUP978.
| Variable | Default | Description |
|---|---|---|
DUMP978_ENABLE_FAUP978 |
Profile-dependent | Enable faup978 service (true/false) |
FAUP978_CONNECT |
localhost:30978 |
Override host:port to connect to |
You can supply custom config files via volume mounts:
volumes:
- ./my-dump978-config:/config/dump978-fa:ro
- ./my-skyaware978-config:/config/skyaware978:ro
- ./my-skyaware-config.js:/config/skyaware978-config.js:roThe container runs four services under s6-overlay:
- dump978-fa — the main 978 MHz UAT decoder that talks to the SDR hardware via SoapySDR, demodulates UAT data, and provides raw and JSON-decoded messages on TCP ports
- skyaware978 — connects to dump978-fa and writes JSON files suitable for the SkyAware web map interface
- nginx — serves the SkyAware978 HTML interface and live aircraft JSON data
- faup978 (optional, profile-dependent) — re-encodes UAT messages and reports to FlightAware for stats collection. Enabled by default with the
flightawareprofile; override withDUMP978_ENABLE_FAUP978=true
The container requires access to the USB SDR device. Pass --device /dev/bus/usb:/dev/bus/usb to grant USB access, or pass only the specific device node.
If using multiple RTL-SDR dongles (e.g., one for 1090 MHz and one for 978 MHz), use the serial number to select the correct dongle:
-e DUMP978_SDR=driver=rtlsdr,serial=978Assign serial numbers to dongles using rtl_eeprom -s 978.
-
Verify USB device passthrough is configured:
docker exec dump978 lsusb docker exec dump978 SoapySDRUtil --find
-
If the device is not visible:
- Ensure
--device /dev/bus/usb:/dev/bus/usbis set - Check that no other process (e.g., kernel DVB driver) is claiming the device
- Blacklist the kernel DVB driver:
echo 'blacklist dvb_usb_rtl28xxu' | sudo tee /etc/modprobe.d/blacklist-rtlsdr.conf
- Ensure
-
Check that dump978-fa is running and connected to the SDR:
docker exec dump978 s6-svstat /run/service/svc-dump978-fa docker logs dump978 --tail 50 -
Verify you are in an area with 978 MHz UAT traffic (US only — UAT is not used outside the United States)
Map to different host ports:
docker run ... -p 9978:8978 -p 31978:30978 -p 31979:30979 ...docker logs dump978
docker logs dump978 --tail 100 -fdocker exec dump978 s6-svstat /run/service/svc-dump978-fa
docker exec dump978 s6-svstat /run/service/svc-skyaware978
docker exec dump978 s6-svstat /run/service/svc-nginx- Check upstream dump978 documentation
- Review container logs:
docker logs -f dump978 - Open an issue on GitHub
This project uses semantic versioning:
- Releases published on GitHub Releases
- Multi-arch images (amd64, arm64v8) built automatically
- Docker Hub tags: version-specific,
latest, and architecture-specific
Update to latest:
docker pull blackoutsecure/dump978:latest
docker-compose up -d # if using composeCheck image version:
docker inspect -f '{{ index .Config.Labels "build_version" }}' blackoutsecure/dump978:latest- Questions: GitHub Issues
- Bug Reports: Include Docker version, container logs, and reproduction steps
- Upstream Documentation: dump978 on GitHub
Get help:
docker logs dump978 # View container logs
docker exec -it dump978 /bin/bash # Access container shell
docker inspect blackoutsecure/dump978 # Check image detailsSponsored and maintained by Blackout Secure
Upstream project: flightaware/dump978 Container patterns: LinuxServer.io
| Resource | Link |
|---|---|
| Docker Hub | blackoutsecure/dump978 |
| GitHub Issues | Report bugs or request features |
| GitHub Releases | Download releases |
| Project | Link |
|---|---|
| dump978 | flightaware/dump978 |
| readsb | wiedehopf/readsb |
| LinuxServer.io | linuxserver.io |
This project is licensed under the MIT License - see the LICENSE file for details.
The upstream dump978 application is licensed under the BSD 2-Clause License. For more information, see the dump978 repository.
Made with confidence by Blackout Secure
