Advanced Installation
For Docker, Ultrafeeder, and custom ADS-B environments
Ultrafeeder / adsb.im Recommended for Docker users
Already running SDR-Enthusiasts Ultrafeeder? Add ADSBiq in 3 minutes — two lines in your config.
1. Generate your feeder UUID (run once):
cat /proc/sys/kernel/random/uuid
2. Add to your .env file:
ADSBIQ_UUID=paste-your-uuid-here
3. Add these two lines to ULTRAFEEDER_CONFIG in your docker-compose.yml:
adsb,feed.adsbiq.com,30004,beast_reduce_plus_out,uuid=$${ADSBIQ_UUID};
mlat,feed.adsbiq.com,31090,uuid=$${ADSBIQ_UUID},name=$${FEEDER_NAME}
4. Restart and verify:
docker compose up -d
docker logs ultrafeeder 2>&1 | grep "feed.adsbiq.com"
You should see: Connection established: feed.adsbiq.com (44.193.85.251) port 30004
5. Register your feeder (run once):
curl -sX POST https://adsbiq.com/api/register \
-H "Content-Type: application/json" \
-d '{"uuid":"YOUR_UUID","name":"YOUR_NAME","lat":YOUR_LAT,"lng":YOUR_LNG,"alt":YOUR_ALT}'
This returns your api_token (starts with iq_) — save it for API access from anywhere. Or visit /join from your feeder's network to register via the web.
Complete Docker Compose Example
Starting from scratch with Ultrafeeder? Here's a tested, working config:
.env file:
# Generate UUID: cat /proc/sys/kernel/random/uuid
ADSBIQ_UUID=paste-your-uuid-here
FEEDER_LAT=26.645
FEEDER_LONG=-80.085
FEEDER_ALT_M=5
FEEDER_NAME=my-feeder
TZ=America/New_York
docker-compose.yml:
services:
ultrafeeder:
image: ghcr.io/sdr-enthusiasts/docker-adsb-ultrafeeder:latest
container_name: ultrafeeder
hostname: ${FEEDER_NAME}
restart: unless-stopped
device_cgroup_rules:
- "c 189:* rwm"
volumes:
- /dev/bus/usb:/dev/bus/usb
- ./globe_history:/var/globe_history
- ./graphs1090:/var/lib/collectd
tmpfs:
- /run:exec,size=256M
- /tmp:size=128M
- /var/log:size=32M
ports:
- "8080:80"
environment:
- TZ=${TZ}
- FEEDER_LAT=${FEEDER_LAT}
- FEEDER_LONG=${FEEDER_LONG}
- FEEDER_ALT_M=${FEEDER_ALT_M}
- FEEDER_NAME=${FEEDER_NAME}
- READSB_LAT=${FEEDER_LAT}
- READSB_LON=${FEEDER_LONG}
- READSB_ALT=${FEEDER_ALT_M}m
- READSB_DEVICE_TYPE=rtlsdr
- READSB_GAIN=autogain
- UUID=${ADSBIQ_UUID}
- MLAT_USER=${FEEDER_NAME}
- ULTRAFEEDER_CONFIG=
adsb,feed.adsbiq.com,30004,beast_reduce_plus_out,uuid=${ADSBIQ_UUID};
mlat,feed.adsbiq.com,31090,uuid=${ADSBIQ_UUID},name=${FEEDER_NAME}
- TAR1090_SITESHOW=true
- TAR1090_SITENAME=${FEEDER_NAME}
- TAR1090_ENABLE_AC_DB=true
- GRAPHS1090=true
With multiple aggregators:
- ULTRAFEEDER_CONFIG=
adsb,feed.adsbiq.com,30004,beast_reduce_plus_out,uuid=${ADSBIQ_UUID};
mlat,feed.adsbiq.com,31090,uuid=${ADSBIQ_UUID},name=${FEEDER_NAME};
adsb,in.adsb.lol,30004,beast_reduce_plus_out;
mlat,in.adsb.lol,31090;
adsb,feed.adsb.fi,30004,beast_reduce_plus_out;
mlat,feed.adsb.fi,31090;
adsb,feed.airplanes.live,30004,beast_reduce_plus_out;
mlat,feed.airplanes.live,31090
Requirements
- Docker 20.10+ and Docker Compose v2+ (install:
curl -fsSL https://get.docker.com | sudo sh) - Supported SDR hardware: RTL-SDR Blog V3/V4, generic RTL2832U, FlightAware Pro Stick (Plus), Airspy Mini/R2 (set
READSB_DEVICE_TYPEaccordingly) - Supported platforms: Raspberry Pi 3B+/4/5, x86_64, Orange Pi, any Linux with Docker and USB
- OS: Raspberry Pi OS Bookworm+, Debian 11+, Ubuntu 22.04+. Buster (Debian 10) is EOL and Docker will not install
- Disk: ~1 GB for the Ultrafeeder image, plus ~500 MB for globe_history and graphs over time
- RAM: 512 MB minimum, 1 GB recommended
Native Install — Platform Compatibility
The standard install script (curl -sL adsbiq.com/install.sh | sudo bash) includes pre-built mlat-client wheels for fast installation — no compiler needed. If no wheel matches your platform, it falls back to building from source automatically.
| Platform | Architecture | Python | OS | mlat-client |
|---|---|---|---|---|
| Raspberry Pi 4/5 | aarch64 |
3.11 | Bookworm | Pre-built wheel |
| Raspberry Pi 4/5 | aarch64 |
3.13 | Trixie | Pre-built wheel |
| Raspberry Pi 3B+/Zero 2W | armv7l |
3.11 | Bookworm (32-bit) | Pre-built wheel |
| x86_64 Server/VM | x86_64 |
3.12 | Ubuntu 24.04 | Pre-built wheel |
| Other | any | 3.9+ | Debian 11+ | Source build (2-5 min) |
Pre-built wheels install in under 10 seconds. Source builds require python3-dev, build-essential, and git (installed automatically). Python 3.12+ systems get pyasyncore polyfill automatically.
Important Notes
- MLAT requires coordinates. Both
READSB_LAT/READSB_LONandFEEDER_LAT/FEEDER_LONGmust be set. Without them, MLAT is silently disabled and you'll see:ERROR: READSB_LAT or LAT must be defined - MLAT will be disabled - MLAT needs a station name. Pass
name=${FEEDER_NAME}in the mlat config line (as shown above) or setMLAT_USERglobally. Without it, Ultrafeeder assigns a random number - One SDR per container. If you run two Ultrafeeder containers with
READSB_DEVICE_TYPE=rtlsdr, the second will fail withDevice or resource busy. UseREADSB_RTLSDR_DEVICEto select by serial number if you have multiple SDRs - Beast feed uses
beast_reduce_plus_out— deduplicates messages at 250ms intervals and tags with your UUID. This reduces bandwidth 60-80% compared to raw Beast output. No configuration needed; Ultrafeeder handles it - No conflicts with other feeds. ADSBiq runs alongside adsb.fi, adsb.lol, airplanes.live, FlightAware, FR24, RadarBox, and any other aggregator. Each semicolon-separated entry in
ULTRAFEEDER_CONFIGruns independently - Registration is separate. Ultrafeeder sends Beast/MLAT data but doesn't call the ADSBiq registration API. Register via
curl(step 5 above) or visit /join from your feeder's network
Troubleshooting
| No aircraft | Check SDR connection: docker exec ultrafeeder lsusb | grep RTL. If missing, reseat the USB dongle. Indoor antennas need 1-2 minutes to pick up signals. |
| MLAT disabled | Set both READSB_LAT/READSB_LON AND FEEDER_LAT/FEEDER_LONG. Check: docker logs ultrafeeder 2>&1 | grep mlat |
| Device busy | Another process (dump1090-fa, another container) is using the SDR. Stop it: sudo systemctl stop dump1090-fa or remove the other container. |
| No connection to ADSBiq | Ensure outbound TCP ports 30004 and 31090 are not blocked by your firewall. Check: docker logs ultrafeeder 2>&1 | grep "feed.adsbiq.com" |
| Wrong device type | Set READSB_DEVICE_TYPE to match your hardware: rtlsdr, miri, bladerf, or plutosdr. Airspy requires the sdr-enthusiasts/docker-adsb-ultrafeeder:telegraf image tag. |
| Network recovery | Ultrafeeder auto-reconnects after network outages. No manual intervention needed — Beast and MLAT connections resume automatically within 30 seconds. |
Verify Everything Works
# Check container health
docker ps | grep ultrafeeder
# Check Beast feed connection
docker logs ultrafeeder 2>&1 | grep "feed.adsbiq.com.*established"
# Check MLAT connection
docker logs ultrafeeder 2>&1 | grep "mlat-client.*feed.adsbiq.com"
# Check aircraft count
curl -s http://localhost:8080/data/aircraft.json | python3 -c "
import sys,json; d=json.load(sys.stdin)
ac=d.get('aircraft',[])
print(f'Aircraft: {len(ac)}, With position: {len([a for a in ac if \"lat\" in a])}')"
# View local map
echo "Open http://$(hostname -I | awk '{print $1}'):8080 in your browser"
Standalone Docker Sidecar alongside existing readsb/dump1090
Not using Ultrafeeder? Run ADSBiq as a sidecar container that reads Beast data from your existing decoder:
docker run -d --name adsbiq \
--restart=unless-stopped \
-e READSB_HOST=readsb \
-e LAT=${LAT} \
-e LON=${LON} \
ghcr.io/adsbiq/feed:latest
Set READSB_HOST to your readsb container name or host.docker.internal for a host-mode decoder.