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_TYPE accordingly)
  • 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_LON and FEEDER_LAT/FEEDER_LONG must 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 set MLAT_USER globally. 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 with Device or resource busy. Use READSB_RTLSDR_DEVICE to 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_CONFIG runs 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.

← Back to simple install