Skip to content
This repository has been archived by the owner on Oct 6, 2021. It is now read-only.

Guide to ADS B Data Receiving, Decoding and Sharing, Leveraging RTLSDR and Docker

Mike Nye edited this page May 6, 2020 · 56 revisions

Guide to ADS-B Data Reception, Decoding & Sharing with RTLSDR & Docker

Automatic Dependent Surveillance-Broadcast (ADS-B) is a surveillance technology in which an aircraft determines its position via satellite navigation and periodically broadcasts it, enabling it to be tracked.

This ADSB-B data can be received by nerds enthusiasts using Software Defined Radio (SDR), and used for fun and profit. For example:

Fun:

Profit:

This guide will go through the process to deploy and configure Docker containers to allow reception and decoding of ADS-B data, as well as submission to various flight tracking services, both open and commercial.


Table of Contents

Dedication

One day I arrived at work, sat down at my desk, probably sighed and looked wistfully into the distance as I thought about getting my morning coffee. My good friend and work colleague Jay wheeled his chair over. "I've got you something!" he said enthusiastically whilst placing a small cardboard box on the edge of my desk, completely out of the blue. "What is this?" I suspiciously said while sizing him up as I opened the box. Inside the box was a FlightAware Pro-Stick Blue with an antenna! This thoughtful gift spurred my somewhat unhealthy obsession with flight tracking.

Thanks Jay. You're a good bloke.

Introduction

Overview

This document aims to guide you through:

The core set of containers consists of: readsb, adsbexchange, piaware, fr24feed and tar1090.

These are deployed (in conjunction with RTL-SDR hardware) as follows:

To explain the flowchart above:

  • ADS-B transmissions are received bia the 1090MHz antenna and RTL-SDR dongle
  • The RTL-SDR dongle device is mapped through to a readsb container, this container's function is to decode the ADS-B transmissions and makes them available via several protocols (BaseStation, Beast, BeastReduce, raw, VRS)
  • There are then three feeder containers:
    • piaware - this container reads Beast protocol data from readsb and submits flight data to the FlightAware service, and get their "Enterprise" feature set in return.
    • adsbx - this container reads Beast protocol data from readsb and submits flight data to the ADSBExchange service.
    • fr24 - this container reads Beast protocol data from readsb and submits flight data to the FlightRadar24 service, and get their "Business Plan" in return.
  • Flight data is visualised using tar1090, presenting a web interface allowing you to view the flight data received by you set-up in real time.

This is considered the "core" set-up. There are other visualisation packages available (eg: FlightAirMap/VirtualRadarServer/Grafana) that you may wish to consider, however keep in mind that these may require quite a bit more horsepower than a Raspberry Pi can provide. tar1090 is very lightweight which is why it is recommended here.

All of the containers I list below will run on:

  • linux/amd64 ("modern" Intel/AMD PCs/servers)
  • linux/arm/v7 (Most Raspberry Pis operating systems)
  • linux/arm64 (Raspberry Pis running aarch64 operating systems)

This mix of architectures allows you to run this set-up this on almost any Linux machine.

I'd like to include other feeders, however in order to do this I need to be able to either:

  • Compile their feeder code myself; or
  • Get my hands on pre-build binaries for all three of the aformentioned platforms

Unfortunately not all feeders make their source/binaries available for all platforms.

If there's another feeder you'd like added as a container, please reach out to me via the methods outlined below.

How to Get Help

You can get help by joining the ADSBExchange Discord, and asking you question in the #docker-help channel, or messaging me (mikenye) directly. I'm in Western Australia so if you don't get a response immediately it might be due to timezones/sleep.

Furthermore, I welcome any feedback on this document. If you think a section needs better instructions or further explanation, or if anything doesn't work for you, please let me know through the channels above so that I can continue to improve this document.

Why Docker

Mainly for Isolation. Dependencies or settings within a container will not affect any installations or configurations on the host computer, or on any other containers that may be running. By using separate containers for different parts of the ADSB reception/decode/submission processes, it means the multiple types and versions of software used for each process will not interfere with each other. Bringing online the ability to feed your ADSB data to another service becomes very simple - just starting another container without having to worry about software conflicts.

Furthermore, the machine running ADSB containers can also function as a Plex Server, an OwnCloud Server, a VM Host etc, meaning that you don't need a separate machine just for feeding ADSB data. This means there's less equipment to break and less power used.

Equipment Needed

To get started, you'll need:

  • A SDR that can receive 1090MHz. I personally use a FlightAware Pro Stick Plus. However, a $20 USB DVB-T RTL2832U dongle will do the job.
  • An antenna optimised for 1090MHz. I use a cheap eBay version of this. You could also make your own.
  • A computer running Linux, capable of running Docker, with a USB port. This can be a Raspberry Pi or an x86 desktop.
  • Cables:
    • USB cable to connect the SDR to the computer. I use a 20m active USB cable (similar to this) which runs from the Linux computer in my study up into my roof, where the SDR and antenna are located.
    • Coaxial cable to connect the antenna to the SDR. As my SDR is located just below my antenna, I use a "pigtail" similar to this.

There's a whole bunch of additional equipment that you could purchase and use, such as 1090MHz bandpass filters, amplifiers, etc etc. This is somewhat outside the scope of this document. If you want more information, I'd refer you to: https://flightaware.com/adsb/piaware/build

Information Needed

During this process, you'll need:

  • The latitude and longitude of your antenna (to at least five decimal places). To find this, you can either use a GPS, or use maps.google.com to zoom in on the exact spot of your antenna, and click to get the latitude and longitude.
  • The altitude (above sea level) of your antenna. To find this, you can either use a GPS, or use something like https://www.freemaptools.com/elevation-finder.htm to zoom in on the exact spot of your antenna, and then add the distance above ground level your antenna is located.

Setting up the Host System

Install Docker

Follow the instructions located here: https://docs.docker.com/install/

In short, you should be able to enter the following commands at your shell, which will automate the docker installation process:

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

After the above installation script finishes running, you should be able to test your docker installation by issuing the command:

docker run --rm hello-world

You should be presented with the following output:

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Install Docker Compose

Follow the instructions located here: https://docs.docker.com/compose/install/

In short, you should be able to enter the following commands at your shell, which will install the latest version of docker-compose:

sudo apt-get install -y libffi-dev libssl-dev python python-pip
sudo pip install docker-compose

After performing the above commands, you can test docker-compose by having it print its version:

docker-compose --version

...which should return something similar to:

docker-compose version 1.25.4, build unknown

Configure Docker

Before starting any containers, you'll want to configure docker container log rotation. This is important, as without log rotation, each container's log will grow in size until it consumes all the disk space available to /var/lib/docker/containers.

To configure docker log rotation, follow the instructions located here: https://success.docker.com/article/how-to-setup-log-rotation-post-installation

It should be noted that on your system the file /etc/docker/daemon.json will likely not exist. Just create a new file at that path and proceed with the instructions.

Blacklist RTL-SDR Kernel Modules

You can skip this step if you're not using an RTLSDR radio (ie: bladeRF).

Before we can plug in our RTLSDR dongle, we need to blacklist the kernel modules for the RTL-SDR USB device from being loaded into the host's kernel and taking ownership of the device.

To do this, create a file /etc/modprobe.d/blacklist-rtl2832.conf containing the following:

blacklist rtl2832
blacklist dvb_usb_rtl28xxu
blacklist rtl2832_sdr

Failure to do this will result in the error below being spammed to the readsb container log.

usb_claim_interface error -6
rtlsdr: error opening the RTLSDR device: Device or resource busy

If you get the error above even after blacklisting the kernel modules as outlined above, the modules may still be loaded. You can unload them by running the following commands:

sudo rmmod rtl2832_sdr
sudo rmmod dvb_usb_rtl28xxu
sudo rmmod rtl2832

Deploying readsb

Readsb (Portmanteau of Read ADSB) is a Mode-S/ADSB/TIS decoder for RTLSDR, BladeRF, Modes-Beast and GNS5894 devices. I've created a docker image mikenye/readsb that contains readsb and all of its required prerequisites and libraries. This is the foundation of our ADSB environment, as it receives and decodes the ADSB data, making it available for all other applications.

To do this, perform the following:

Connect SDR hardware

Plug in your RTLSDR dongle, bladeRF or whatever SDR you're using.

Run the command lsusb and find your radio. It'll look something like this:

For RTL-SDR:

Bus 001 Device 004: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T

For bladeRF:

Bus 001 Device 004: ID 1d50:6066 OpenMoko, Inc. Nuand BladeRF

Take note of the bus number, and device number. In each output above, its 001 and 004 respectively.

Create a directory to host our docker-compose.yml file

I'm using /opt/adsb.

mkdir -p /opt/adsb
cd /opt/adsb

Create docker-compose.yml file

In your favourite text editor, create a file named docker-compose.yml.

Place the following text into it:

version: '2.0'

networks:
  adsbnet:

services:

  readsb:
    image: mikenye/readsb:latest
    tty: true
    container_name: readsb
    restart: always
    devices:
      - /dev/bus/usb/BUSNUMBER/DEVICENUMBER:/dev/bus/usb/BUSNUMBER/DEVICENUMBER
    ports:
      - 8080:8080
      - 30005:30005
    networks:
      - adsbnet
    command:
      - --dcfilter
      - --device-type=rtlsdr
      - --fix
      - --forward-mlat
      - --json-location-accuracy=2
      - --lat=YOURLATITUDE
      - --lon=YOURLONGITUDE
      - --mlat
      - --modeac
      - --ppm=0
      - --net
      - --stats-every=3600
      - --quiet
      - --write-json=/var/run/readsb

Note: if you're using bladeRF, you'll need to change --device-type=rtlsdr to --device-type=bladerf.

Be sure to change the following:

  • Replace BUSNUMBER with the bus number of your radio, from the lsusb output from earlier
  • Replace DEVICENUMBER with the device number of your radio, from the lsusb output from earlier
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)

So, assuming:

  • Output from lsusb shows the RTLSDR as Bus 001 Device 004: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T, BUSNUMBER would be 001 and DEVICENUMBER would be 004.
  • Our latitude is -33.33333 and longitude is 111.11111

...then our docker-compose.yml file would be as follows:

version: '2.0'

networks:
  adsbnet:

services:

  readsb:
    image: mikenye/readsb:latest
    tty: true
    container_name: readsb
    restart: always
    devices:
      - /dev/bus/usb/001/004:/dev/bus/usb/001/004
    ports:
      - 8080:8080
      - 30005:30005
    networks:
      - adsbnet
    command:
      - --dcfilter
      - --device-type=rtlsdr
      - --fix
      - --forward-mlat
      - --json-location-accuracy=2
      - --lat=-33.33333
      - --lon=111.11111
      - --mlat
      - --modeac
      - --ppm=0
      - --net
      - --stats-every=3600
      - --quiet
      - --write-json=/var/run/readsb

Note: if you're using bladeRF, you'll need to change --device-type=rtlsdr to --device-type=bladerf.

To explain what's going on in this file:

  • We're creating a new docker network called adsbnet, which will be used to allow other containers to communicate with this container.
  • We're creating a container called readsb, from the image mikenye/readsb:latest.
  • We're passing through the RTLSDR (USB device 004 on bus 001) to the container.
  • We're passing through TCP port 8080 on the host to port 8080 on the container, so we can view the web interface at http://dockerhost:8080/.
  • We're passing through TCP port 30005 on the host to port 30005 on the container, so other applications can receive the ADSB data generated by readsb.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several command line arguments to readsb, most notably:
    • --device-type=rtlsdr to inform readsb to look for an RTLSDR device. If you use a bladeRF device, you should change this to --device-type=bladerf.
    • --lat=-33.33333 to inform readsb of the antenna's latitude
    • --lon=111.11111 to inform readsb of the antenna's longitude
    • --write-json=/var/run/readsb to inform readsb to output JSON data to /var/run/readsb (for the web interface to function correctly)

If you're using bladeRF, you may need some additional settings depending on your hardware, eg:

      - --device-type=bladerf
      - --bladerf-fpga=/usr/share/readsb/bladerf/decimate8-x40.rbf
      - --bladerf-decimation=8
      - --bladerf-bandwidth=14000000

Once the file is created, issue the command docker-compose up -d to bring up the ADSB environment. You should see the following output:

Creating network “adsb_adsbnet” with the default driver
Creating readsb

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

readsb   | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
readsb   | [s6-init] ensuring user provided files have correct perms...exited 0.
readsb   | [fix-attrs.d] applying ownership & permissions fixes...
readsb   | [fix-attrs.d] done.
readsb   | [cont-init.d] executing container initialization scripts...
readsb   | [cont-init.d] done.
readsb   | [services.d] starting services
readsb   | [services.d] done.
readsb   | Wed Feb 19 07:23:48 2020 UTC Mictronics v3.8.1 starting up.
readsb   | rtlsdr: using device #0: Generic RTL2832U (Realtek, RTL2832U, SN 00001000)
readsb   | Found Rafael Micro R820T tuner
readsb   | Allocating 16 zero-copy buffers
readsb   | Failed to allocate zero-copy buffer for transfer 0
readsb   | Falling back to buffers in userspace

We can see our container running with the command docker ps, and see the adsb_adsbnet network with the command docker network ls.

Viewing live data from readsb

To see the data being received and decoded by our new container, run the command docker exec -it readsb viewadsb. This should display a real-time departure-lounge-style screen showing all the aircraft being tracked, for example:

Hex  Mode Sqwk Flight  Alt  Spd Hdg  Lat   Long  RSSI Msgs Ti |
────────────────────────────────────────────────────────────────────────────────
 7C80BF S   3711 JTE834  14650 373 098 -32.113 116.352 -24.0  383 0
 7C30FE S   1200 JYO    6050 115 052 -32.594 115.770 -24.9  161 0
 7C7181 S   0064 POL64   4375 116 345 -32.776 115.888 -29.0  62 0
 7CF9D8 S   2063 VIPR44  2150 285 077 -31.523 116.128 -25.9  408 0
 7C81D8 S   3757 ZXM   23075 278 010 -30.979 116.699 -28.6  455 0
 7C7A68 S   3000 YGQ    950  83 324 -32.088 115.913 -26.2  602 0
 7C7A71 S   3000 YGZ    675  66 236 -32.106 115.868 -26.1  90 0
 7C42D5 S   4264 NWK1646 33000 399 004 -30.147 116.497 -27.5  364 0
 7502D8 S                           -37.2   3 40
 7C42DB S   7236 NWK1612 15000 329 346 -31.757 115.559 -19.1  495 0
 7C4321 S   4242 JTE724  24000 383 357 -31.297 116.795 -27.5  410 0
 7C4324 S   3707      21825 366 058 -31.829 117.191 -30.9  22 12
 7C1B26 S   4212 VOZ9233 22825 364 351 -31.488 115.524 -13.0  299 0
 7C6C25 S   3713       grnd  9 284          -23.4   9 2
 7C7C53 S   4341 VOZ9265 31675 446 023 -31.087 115.986 -17.5  502 0
 7C1468 S   3752 QFA577  2650 191 232 -31.795 116.014 -6.8  740 0
 7C752D S   4045 VOZ562   grnd  3 253          -22.1  44 2
 7C4530 S   3661 NYA    8550 176 052 -31.954 116.159 -12.7  575 0
 7C6D9A S   4257 QFA1129  grnd 21 231 -31.946 115.963 -27.8  54 25
 7C75E5 S                           -39.8   2 49
 7C6DEB S           grnd  7 000          -28.8   3 6
 76E726 S   7316 MONS11  1300 247 173 -31.610 116.015 -27.6  29 2
 7C7796 S           grnd  6 284          -28.4   6 2
 7C7797 S   7210 UTY6046  3525 215 269 -32.024 115.905 -3.9  650 0
 7CF7C4 S      PHRX1A                   -13.2  78 0
 7CF7C5 S      PHRX1B                   -13.5  79 0
 7CF7C6 S      PHRX2A                   -32.8   2 4
 7C2FDB S          35275 458 002 -30.144 116.161 -31.4  44 5

Press CTRL-C to escape this screen.

You should also be able to point your web browser at http://dockerhost:8080/ to view the web interface. At the time of writing this readme (readsb v3.8.3), the webapp is still being developed. I was able to get a usable interface with Firefox.

If you need to bring the environment down (for example, if you need to unplug the RTLSDR USB dongle for maintenance), you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Feeding adsbexchange.com

ADSBexchange.com is a co-op of ADS-B/Mode S/MLAT feeders from around the world, and the world’s largest source of unfiltered flight data.

Generating a UUID for your receiver

In order to generate a site UUID, initially run the container with the following command:

docker run --rm -it --entrypoint uuidgen mikenye/adsbexchange -t

Take note of the UUID returned.

Deploying adsbexchange.com feeder container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  adsbx:
    image: mikenye/adsbexchange:latest
    tty: true
    container_name: adsbx
    restart: always
    environment:
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE
      - SITENAME=YOURSITENAME
      - UUID=YOURUUID
    networks:
      - adsbnet

Be sure to change the following:

  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude above sea level of your antenna. If specified in feet, add the suffix ft. If specified in metres, add the suffix m
  • Replace YOURSITENAME with a unique name for your receiver, using only the characters "A-Z", "a-z", (-) and (_)
  • Replace YOURUUID with the UUID that was generated in the previous step

So, assuming:

  • Our latitude is -33.33333 and longitude is 111.11111
  • Our altitude is 95m
  • Our site name is My_Cool_ADSB_Receiver
  • Our generated UUID is 4e8413e6-52eb-11ea-8681-1c1b0d925d3g

...then our docker-compose.yml file would be appended with the following:

  adsbx:
    image: mikenye/adsbexchange:latest
    tty: true
    container_name: adsbx
    restart: always
    environment:
      - BEASTHOST=readsb
      - LAT=-33.33333
      - LONG=111.11111
      - ALT=95m
      - SITENAME=My_Cool_ADSB_Receiver
      - UUID=4e8413e6-52eb-11ea-8681-1c1b0d925d3g
    networks:
      - adsbnet

To explain what's going on in this addition:

  • We're creating a container called adsbx, from the image mikenye/adsbexchange:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333 to inform the feeder of the antenna's latitude
    • LONG=111.11111 to inform the feeder of the antenna's longitude
    • ALT=95m to inform the feeder of the antenna's altitude
    • SITENAME=My_Cool_ADSB_Receiver to inform the feeder of our site name
    • UUID=4e8413e6-52eb-11ea-8681-1c1b0d925d3g to inform the feeder of our UUID

Once the file is created, issue the command docker-compose up -d to bring up the ADSB environment. You should see the following output:

readsb is up-to-date
Creating adsbx

You can see from the output above that the readsb container was left alone (as the configuration for this container did not change), and a new container adsbx was created.

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. We should now see logs from our newly created adsbx container:

adsbx   | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
adsbx   | [s6-init] ensuring user provided files have correct perms...exited 0.
adsbx   | [fix-attrs.d] applying ownership & permissions fixes...
adsbx   | [fix-attrs.d] done.
adsbx   | [cont-init.d] executing container initialization scripts...
adsbx   | [cont-init.d] 01-adsbexchange: executing...
adsbx   | Statistics will be available at: https://www.adsbexchange.com/api/feeders/?feed=4e8413e6-52eb-11ea-8681-1c1b0d925d3g
adsbx   | [cont-init.d] 01-adsbexchange: exited 0.
adsbx   | [cont-init.d] done.
adsbx   | [services.d] starting services
adsbx   | [services.d] done.
adsbx   | [adsbexchange-stats] Using UUID 4e8413e6-52eb-11ea-8681-1c1b0d925d3g for stats uploads...
adsbx   | [adsbexchange-stats] Using JSON directory /run/readsb for source data...
adsbx   | [adsbexchange-feed] Wed Feb 19 15:47:22 2020 AWST Mictronics v3.8.1 starting up.
adsbx   | [adsbexchange-feed] Net-only mode, no SDR device or file open.
adsbx   | [mlat-client] Wed Feb 19 15:47:22 2020 mlat-client 0.2.10 starting up
adsbx   | [adsbexchange-feed] Beast TCP input: Connection established: readsb (192.168.213.98) port 30005
adsbx   | [mlat-client] Wed Feb 19 15:47:23 2020 Connected to multilateration server at feed.adsbexchange.com:31090, handshaking
adsbx   | [adsbexchange-feed] BeastReduce TCP output: Connection established: feed.adsbexchange.com (167.114.60.74) port 30005
adsbx   | [mlat-client] Wed Feb 19 15:47:23 2020 Beast-format results connection with 192.168.213.98:30005: connection established
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Server says:
adsbx   | [mlat-client]
adsbx   | [mlat-client]     In-development v2 server. Expect odd behaviour.
adsbx   | [mlat-client]
adsbx   | [mlat-client]     The multilateration server source code is available under
adsbx   | [mlat-client]     the terms of the Affero GPL (v3 or later). You may obtain
adsbx   | [mlat-client]     a copy of this server’s source code at the following
adsbx   | [mlat-client]     location: https://github.com/adsbexchange/mlat-server
adsbx   | [mlat-client]
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Handshake complete.
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020  Compression:    zlib2
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020  UDP transport:   disabled
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020  Split sync:    disabled
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Input connected to readsb:30005
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Input format changed to BEAST, 12MHz clock

After a few minutes, point your browser at https://adsbexchange.com/myip/. You should see two green smiley faces indicating that you are successfully sending data.

Deploying tar1090 for improved visualisation

tar1090 is an excellent tool by wiedehopf that improves on the dump1090-fa interface (used by PiAware's "SkyAware").

This is my personal preference for displaying real-time ADS-B information.

Deploying tar1090 container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  tar1090:
    image: mikenye/tar1090:latest
    tty: true
    container_name: tar1090
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
    networks:
      - adsbnet
    ports:
      - 8078:80

Be sure to change the following:

So, assuming:

  • Our timezone is Australia/Perth

...then our docker-compose.yml file would be appended with the following:

  tar1090:
    image: mikenye/tar1090:latest
    tty: true
    container_name: tar1090
    restart: always
    environment:
      - TZ=Australia/Perth
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - LAT=-33.33333
      - LONG=111.11111
    networks:
      - adsbnet
    ports:
      - 8078:80

To explain what's going on in this file:

  • We're creating a container called tar1090, from the image mikenye/tar1090:latest.
  • We're passing through TCP port 8078 on the host to port 80 on the container, so we can get to the tar1090 web interface at http://dockerhost:8078/.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • LAT and LONG to tell the container our home position.
    • BEASTHOST=readsb to inform graphs1090 to get its ADSB data from the container readsb over our private adsbnet network.
    • MLATHOST=adsbx to inform graphs1090 to get its MLAT data from the container adsbx over our private adsbnet network.

Once the file is created, issue the command docker-compose up -d to bring up the new tar1090 container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
fr24 is up-to-date
Creating tar1090

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

tar1090           | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
tar1090           | [s6-init] ensuring user provided files have correct perms...exited 0.
tar1090           | [fix-attrs.d] applying ownership & permissions fixes...
tar1090           | [fix-attrs.d] done.
tar1090           | [cont-init.d] executing container initialization scripts...
tar1090           | [cont-init.d] 01-tar1090-update: executing...
tar1090           | tar1090 database version: fed120f
tar1090           | tar1090 version: e4f6b2b
tar1090           | [cont-init.d] 01-tar1090-update: exited 0.
tar1090           | [cont-init.d] 02-tar1090-copy: executing...
tar1090           | [cont-init.d] 02-tar1090-copy: exited 0.
tar1090           | [cont-init.d] 03-tar1090-configure: executing...
tar1090           | [cont-init.d] 03-tar1090-configure: exited 0.
tar1090           | [cont-init.d] 04-tar1090-gzip: executing...
tar1090           | [cont-init.d] 04-tar1090-gzip: exited 0.
tar1090           | [cont-init.d] done.
tar1090           | [services.d] starting services
tar1090           | [readsb] Tue Mar 31 22:35:13 2020 AWST  Mictronics v3.8.2 starting up.
tar1090           | [readsb] Net-only mode, no SDR device or file open.
tar1090           | [services.d] done.
tar1090           | [readsb] Beast TCP input: Connection established: readsb (172.22.7.8) port 30005
tar1090           | [readsb] Beast TCP input: Connection established: adsbx (172.22.7.9) port 30005

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8078/ to access the tar1090 web interface.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Deploying graphs1090 for visualising ADSB reception stats

graphs1090 is an excellent tool by wiedehopf that generates graphs for dump1090/readsb and their variants.

This container receives:

  • Beast data from a provider such as readsb
  • MLAT data from a provider such as mlat-client, which is present in the ADSBExchange container we just created

This can help highlight improvement or deterioration in reception performance when adjusting receiver settings (such as gain), or changing antennas.

Deploying graphs1090 container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  graphs1090:
    image: mikenye/graphs1090:latest
    tty: true
    container_name: graphs1090
    restart: always
    volumes:
      - graphs1090_rrd:/var/lib/collectd/rrd
    ports:
      - 8079:80
    environment:
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - TZ=YOURTIMEZONE
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
    networks:
      - adsbnet

Be sure to change the following:

So, assuming:

  • Our latitude is -33.33333 and longitude is 111.11111
  • Our timezone is Australia/Perth

...then our docker-compose.yml file would be appended with the following:

  graphs1090:
    image: mikenye/graphs1090:latest
    tty: true
    container_name: graphs1090
    restart: always
    volumes:
      - graphs1090_rrd:/var/lib/collectd/rrd
    ports:
      - 8079:80
    environment:
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - TZ=Australia/Perth
      - LAT=-33.33333
      - LONG=111.11111
    networks:
      - adsbnet

To explain what's going on in this addition:

  • We're creating a container called graphs1090, from the image mikenye/graphs1090:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're providing persistent storage in the form of a docker volume named graphs1090_rrd, where the round robin databases containing historical statistics will be stored. By providing persistent storage, our statistics will not be lost when the container is recreated by docker-compose.
  • We're passing several environment variables to the container:
    • BEASTHOST=readsb to inform graphs1090 to get its ADSB data from the container readsb over our private adsbnet network.
    • MLATHOST=adsbx to inform graphs1090 to get its MLAT data from the container adsbx over our private adsbnet network.
    • LAT=-33.33333 to inform graphs1090 of the antenna's latitude.
    • LONG=111.11111 to inform graphs1090 of the antenna's longitude.
    • TZ=Australia/Perth so that the graphs generated are in our local timezone.

Once the file is created, issue the command docker-compose up -d to bring up the ADSB environment. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
Creating graphs1090

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

graphs1090        | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
graphs1090        | [s6-init] ensuring user provided files have correct perms...exited 0.
graphs1090        | [fix-attrs.d] applying ownership & permissions fixes...
graphs1090        | [fix-attrs.d] done.
graphs1090        | [cont-init.d] executing container initialization scripts...
graphs1090        | [cont-init.d] 01-sanitycheck: executing...
graphs1090        | [cont-init.d] 01-sanitycheck: exited 0.
graphs1090        | [cont-init.d] done.
graphs1090        | [services.d] starting services
graphs1090        | [graphs1090] Generating all graphs
graphs1090        | collectd[226]: plugin_load: plugin "syslog" successfully loaded.
graphs1090        | [services.d] done.
graphs1090        | [readsb] Tue May  5 15:35:48 2020 AWST  Mictronics v3.8.3 starting up.
graphs1090        | [readsb] Net-only mode, no SDR device or file open.
graphs1090        | collectd[226]: plugin_load: plugin "rrdtool" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "table" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "interface" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "cpu" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "aggregation" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "match_regex" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "df" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "disk" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "python" successfully loaded.
graphs1090        | [readsb] Beast TCP input: Connection established: readsb (192.168.176.8) port 30005
graphs1090        | [readsb] Beast TCP input: Connection established: adsbx (192.168.176.6) port 30105
graphs1090        | collectd[226]: Initialization complete, entering read-loop.

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8079/ to access the graphs1090 graphs.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Feeding FlightAware

PiAware is a FlightAware client program to securely transmit ADS-B and Mode S data to the commercial entity FlightAware.

In exchange for your data, FlightAware will give you an Enterprise Membership. If this is something of interest, you may wish to feed your data to them.

The docker image mikenye/piaware contains piaware and all of its required prerequisites and libraries. This can run standalone (without the readsb container), however for flexibility it is recommended to run with readsb.

Already running PiAware

You'll need your feeder-id from your existing feeder.

To get your feeder-id, log onto your feeder and issue the command:

piaware-config -show feeder-id

New to PiAware

If you're already running PiAware and you've followed the steps in the previous command, you can skip this section.

You'll need a feeder-id. To get one, you can temporarily run the container, to allow it to communicate with the FlightAware servers and get a new feeder ID.

Run the command:

timeout 30 docker run --rm -e LAT=YOURLATITUDE -e LONG=YOURLONGITUDE mikenye/piaware:latest | grep "my feeder ID"

Be sure to change the following:

  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)

The command will run the container for 30 seconds, which should be ample time for the container to receive a feeder-id.

For example:

$ timeout 30 docker run --rm -e LAT=-33.33333 -e LONG=111.11111 mikenye/piaware:latest | grep "my feeder ID"
Set allow-mlat to yes in /etc/piaware.conf:1
Set allow-modeac to yes in /etc/piaware.conf:2
Set allow-auto-updates to no in /etc/piaware.conf:3
Set allow-manual-updates to no in /etc/piaware.conf:4
2020-03-06 06:16:11.860212500  [piaware] my feeder ID is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g
write /dev/stdout: broken pipe
Terminated

As you can see from the output above, the feeder-id given to us from FlightAware is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g.

You'll now want to "claim" this feeder.

To do this, go to: https://flightaware.com/adsb/piaware/claim and follow the instructions there.

Deploying PiAware feeder container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  piaware:
    image: mikenye/piaware:latest
    tty: true
    container_name: piaware
    restart: always
    ports:
      - 8081:8080
    networks:
      - adsbnet
    environment:
      - TZ=YOURTIMEZONE
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - FEEDER_ID=YOURFEEDERID
      - BEASTHOST=readsb

Be sure to change the following:

  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURFEEDERID with the feeder-id from your original receiver or the one you generated in the previous step.

So, assuming:

  • Our latitude is -33.33333 and longitude is 111.11111
  • Our timezone is Australia/Perth
  • Our feeder ID is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g

...then our docker-compose.yml file would be appended with the following:

  piaware:
    image: mikenye/piaware:latest
    tty: true
    container_name: piaware
    restart: always
    ports:
      - 8081:8080
    networks:
      - adsbnet
    environment:
      - TZ=Australia/Perth
      - LAT=-33.33333
      - LONG=111.11111
      - FEEDER_ID=acbf1f88-09a4-3a47-a4a0-10ae138d0c1g
      - BEASTHOST=readsb

To explain what's going on in this file:

  • We're creating a container called readsb, from the image mikenye/readsb:latest.
  • We're passing through TCP port 8081 on the host to port 8080 on the container, so we can view SkyAware at http://dockerhost:8081/.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333 to inform the feeder of the antenna's latitude
    • LONG=111.11111 to inform the feeder of the antenna's longitude
    • FEEDER_ID=acbf1f88-09a4-3a47-a4a0-10ae138d0c1g to identify ourself to FlightAware

Once the file is created, issue the command docker-compose up -d to bring up the new piaware container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
Creating piaware

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

piaware         | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
piaware         | [s6-init] ensuring user provided files have correct perms...exited 0.
piaware         | [fix-attrs.d] applying ownership & permissions fixes...
piaware         | [fix-attrs.d] done.
piaware         | [cont-init.d] executing container initialization scripts...
piaware         | [cont-init.d] 01-piaware: executing...
piaware         | Set feeder-id to acbf1f88-09a4-3a47-a4a0-10ae138d0c1g in /etc/piaware.conf:1
piaware         | Set allow-mlat to yes in /etc/piaware.conf:2
piaware         | Set allow-modeac to yes in /etc/piaware.conf:3
piaware         | Set allow-auto-updates to no in /etc/piaware.conf:4
piaware         | Set allow-manual-updates to no in /etc/piaware.conf:5
piaware         | [cont-init.d] 01-piaware: exited 0.
piaware         | [cont-init.d] done.
piaware         | [services.d] starting services
piaware         | [beastrelay] 2020/03/06 14:01:29 socat[267] N listening on AF=2 0.0.0.0:30005
piaware         | [services.d] done.
piaware         | 2020-03-06 14:01:29.742018500  [httpd] 2020-03-06 14:01:29: (server.c.1521) server started (lighttpd/1.4.54)
piaware         | 2020-03-06 14:01:29.828330500  [dump1090-fa] Fri Mar  6 14:01:29 2020 AWST  dump1090-fa  starting up.
piaware         | 2020-03-06 14:01:29.830284500  [dump1090-fa] Net-only mode, no SDR device or file open.
piaware         | 2020-03-06 14:01:29.835375500  [piaware] ****************************************************
piaware         | 2020-03-06 14:01:29.835417500  [piaware] piaware version 3.8.0 is running, process ID 273
piaware         | 2020-03-06 14:01:29.836659500  [piaware] your system info is: Linux ee1f452gf232 4.4.0-174-generic #204-Ubuntu SMP Wed Jan 29 06:41:01 UTC 2020 x86_64 Linux
piaware         | 2020-03-06 14:01:31.337622500  [piaware] Connecting to FlightAware adept server at piaware.flightaware.com/1200
piaware         | 2020-03-06 14:01:31.588615500  [piaware] Connection with adept server at piaware.flightaware.com/1200 established
piaware         | 2020-03-06 14:01:32.119913500  [piaware] TLS handshake with adept server at piaware.flightaware.com/1200 completed
piaware         | 2020-03-06 14:01:32.161723500  [piaware] FlightAware server certificate validated
piaware         | 2020-03-06 14:01:32.161732500  [piaware] encrypted session established with FlightAware
piaware         | 2020-03-06 14:01:32.861649500  [piaware] ADS-B data program 'socat' is listening on port 30005, so far so good
piaware         | 2020-03-06 14:01:32.869657500  [piaware] Starting faup1090: /usr/lib/piaware/helpers/faup1090 --net-bo-ipaddr localhost --net-bo-port 30005 --stdout
piaware         | 2020-03-06 14:01:32.873773500  [piaware] Started faup1090 (pid 298) to connect to socat
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[267] N accepting connection from AF=2 127.0.0.1:54032 on AF=2 127.0.0.1:30005
piaware         | 2020-03-06 14:01:32.875876500  [piaware] UAT support disabled by local configuration setting: uat-receiver-type
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N opening connection to AF=2 172.99.7.4:30005
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N successfully connected from local address AF=2 172.99.7.3:56186
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N starting data transfer loop with FDs [6,6] and [5,5]
piaware         | 2020-03-06 14:01:32.919203500  [piaware] adept reported location: -33.33333, 111.11111, 90ft AMSL
piaware         | 2020-03-06 14:01:32.921957500  [piaware] Receiver location changed, restarting dump1090 and skyaware978
piaware         | 2020-03-06 14:01:32.922717500  [piaware] attempting to restart dump1090..
piaware         | 2020-03-06 14:01:32.927936500  [piaware] attempting to restart dump1090 using '/etc/init.d/dump1090 restart < /dev/null &'...
piaware         | 2020-03-06 14:01:32.932117500  [piaware] dump1090 restart appears to have been successful
piaware         | 2020-03-06 14:01:32.932906500  [piaware] attempting to restart skyaware978..
piaware         | 2020-03-06 14:01:32.933667500  [piaware] can't restart skyaware978, no services that look like skyaware978 found
piaware         | 2020-03-06 14:01:32.934225500  [piaware] Restarting faup1090
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] W read(6, 0x5586c963d020, 8192): Connection reset by peer
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 1 to socket 2 is in error
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 1 (fd 6) is at EOF
piaware         | 2020-03-06 14:01:32.935602500  [piaware] faup1090 exited with SIG SIGHUP
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 1 (fd 6) is at EOF
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 2 (fd 5) is at EOF2020-03-06 14:01:32.936314500  [piaware] will reconnect to socat in 5 seconds
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N exiting with status 0
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[267] N childdied(): handling signal 17
piaware         | 2020-03-06 14:01:32.937608500  [dump1090-fa] Fri Mar  6 14:01:32 2020 AWST  Caught SIGTERM, shutting down..
piaware         | 2020-03-06 14:01:32.937631500  [dump1090-fa]
piaware         | 2020-03-06 14:01:32.937643500  [dump1090-fa] Fri Mar  6 14:01:32 2020 AWST  Normal exit.
piaware         | 2020-03-06 14:01:32.938035500  [piaware] logged in to FlightAware as user mikenye
piaware         | 2020-03-06 14:01:32.938810500  [piaware] my feeder ID is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8081/ to access PiAware's "SkyAware". You can also log onto FlightAware's website and click on the "My ADSB" link at the top of the page, and see your statistics, configure your location, configure your altitude, etc etc.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Feeding FlightRadar24

fr24feed is a FlightRadar24 client program to securely transmit ADS-B and Mode S data to the commercial entity FlightRadar24.

In exchange for your data, FlightAware will give you a Business Plan. If this is something of interest, you may wish to feed your data to them.

I've created a docker image mikenye/fr24feed that contains fr24feed and all of its required prerequisites and libraries. This needs to run in conjunction with readsb (or another Beast provider).

Already running fr24feed

You'll need your fr24key from your existing feeder.

To get your fr24key, log onto your feeder and issue the command:

cat /etc/fr24feed.ini | grep fr24key

New to fr24feed

If you're already running fr24feed and you've followed the steps in the previous command, you can skip this section.

First-time users should obtain a FlighRadar24 sharing key (a fr24key). To get one, you can run through the signup process. This will ask a series of questions allowing you to sign up with FlightRadar24 and get a fr24key.

Run the command:

docker run --rm -it --entrypoint fr24feed mikenye/fr24feed --signup

This will take you through the signup process. At the end of the signup process, you'll be presented with:

Congratulations! You are now registered and ready to share ADS-B data with Flightradar24.
+ Your sharing key (xxxxxxxxxxxx) has been configured and emailed to you for backup purposes.
+ Your radar id is X-XXXXXXX, please include it in all email communication with us.

Take a note of the sharing key, as you'll need it when launching the container.

Deploying fr24feed container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  fr24:
    image: mikenye/fr24feed:latest
    tty: true
    container_name: fr24
    restart: always
    ports:
      - 8754:8754
    networks:
      - adsbnet
    environment:
      - TZ=YOURTIMEZONE
      - MLAT=yes
      - FR24KEY=YOURFR24KEY
      - BEASTHOST=readsb

Be sure to change the following:

So, assuming:

  • Our timezone is Australia/Perth
  • Our fr24key is 10ae138d0c1g

...then our docker-compose.yml file would be appended with the following:

  fr24:
    image: mikenye/fr24feed:latest
    tty: true
    container_name: fr24
    restart: always
    ports:
      - 8754:8754
    networks:
      - adsbnet
    environment:
      - TZ=Australia/Perth
      - MLAT=yes
      - FR24KEY=10ae138d0c1g
      - BEASTHOST=readsb

To explain what's going on in this file:

  • We're creating a container called fr24, from the image mikenye/fr24feed:latest.
  • We're passing through TCP port 8754 on the host to port 8754 on the container, so we can get to the fr24feed web interface at http://dockerhost:8754/.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • MLAT=yes to enable multilateration.
    • FR24KEY=10ae138d0c1g sets our fr24key.

Once the file is created, issue the command docker-compose up -d to bring up the new fr24 container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
Creating fr24

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

fr24              | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
fr24              | [s6-init] ensuring user provided files have correct perms...exited 0.
fr24              | [fix-attrs.d] applying ownership & permissions fixes...
fr24              | [fix-attrs.d] done.
fr24              | [cont-init.d] executing container initialization scripts...
fr24              | [cont-init.d] 01-fr24feed: executing...
fr24              | [cont-init.d] 01-fr24feed: exited 0.
fr24              | [cont-init.d] done.
fr24              | [services.d] starting services
fr24              | 2020-03-23 16:36:19 | [feed][i]sent 8,6 AC
fr24              | 2020-03-23 16:36:24 | [feed][i]sent 7,7 AC
fr24              | 2020-03-23 16:36:25 | [feed][i]filtering out 9 overlapping AC (saving bandwidth)
fr24              | 2020-03-23 16:36:29 | [main][i]Terminating on user request
fr24              | 2020-03-23 16:36:29 | [main][i]Terminating worker threads
fr24              | 2020-03-23 16:36:30 | [reader][i]Connection terminated
fr24              | 2020-03-23 16:36:30 | [reader][i]Terminating on request
fr24              | 2020-03-23 16:36:31 | [bs][i]Server terminated!
fr24              | 2020-03-23 16:36:31 | [raw][i]Server terminated!
fr24              | 2020-03-23 16:36:33 | [main][i]Forcing process termination
fr24              | [services.d] done.
fr24              | 2020-03-23 16:36:37 | ______  _  _         _      _                    _              _____    ___
fr24              | 2020-03-23 16:36:37 | |  ___|| |(_)       | |    | |                  | |            / __  \  /   |
fr24              | 2020-03-23 16:36:37 | | |_   | | _   __ _ | |__  | |_  _ __  __ _   __| |  __ _  _ __`' / /' / /| |
fr24              | 2020-03-23 16:36:37 | |  _|  | || | / _` || '_ \ | __|| '__|/ _` | / _` | / _` || '__| / /  / /_| |
fr24              | 2020-03-23 16:36:37 | | |    | || || (_| || | | || |_ | |  | (_| || (_| || (_| || |  ./ /___\___  |
fr24              | 2020-03-23 16:36:37 | \_|    |_||_| \__, ||_| |_| \__||_|   \__,_| \__,_| \__,_||_|  \_____/    |_/
fr24              | 2020-03-23 16:36:37 |                __/ |
fr24              | 2020-03-23 16:36:37 |               |___/
fr24              | 2020-03-23 16:36:37 | [main][i]FR24 Feeder/Decoder
fr24              | 2020-03-23 16:36:37 | [main][i]Version: 1.0.25-2/generic
fr24              | 2020-03-23 16:36:37 | [main][i]Built on Mar 11 2020 12:48:08 (FRBACKEND-2065-6d31545.git/Linux/static_amd64)
fr24              | 2020-03-23 16:36:37 | [main][i]Running on: debian10
fr24              | 2020-03-23 16:36:37 | [main][i]Local IP(s): 172.92.4.85
fr24              | 2020-03-23 16:36:37 | [main][i]Copyright 2012-2020 Flightradar24 AB
fr24              | 2020-03-23 16:36:37 | [main][i]https://www.flightradar24.com
fr24              | 2020-03-23 16:36:37 | [main][i]DNS mode: PING
fr24              | 2020-03-23 16:36:37 | [main][i]Automatic updates are DISABLED
fr24              | 2020-03-23 16:36:37 | info | [httpd]Server started, listening on 0.0.0.0:8754
fr24              | 2020-03-23 16:36:37 | [i]PacketSenderConfiguration::fetch_config(): Yoda configuration for this receiver is disabled
fr24              | 2020-03-23 16:36:37 | [d]TLSConnection::ctor(): Enable verify_peer in production code!
fr24              | 2020-03-23 16:36:37 | [main][i]Reader thread started
fr24              | 2020-03-23 16:36:37 | [master][i]Starting processing thread
fr24              | 2020-03-23 16:36:37 | [reader][i]Initializing reader
fr24              | 2020-03-23 16:36:37 | [reader][i]Connecting to unknown receiver via (tcp://readsb:30005)
fr24              | 2020-03-23 16:36:37 | [main][i]Socket server started
fr24              | 2020-03-23 16:36:37 | [main][i]MLAT data feed started

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8754/ to access the fr24feed web interface. You can also log onto FlightAware's website and click on the your profile button, and then "My data sharing" link to see your statistics.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

It is worth noting that fr24feed is extremely noisy when it comes to logging. If you haven't set up Docker log rotation as outlined earlier, consider doing this, lest your /var/lib/docker become full.

Feeding AirNav RadarBox

rbfeeder is a RadarBox client program to transmit ADS-B and Mode S data to the commercial entity RadarBox.

In exchange for your data, RadarBox will give you a Business Plan. If this is something of interest, you may wish to feed your data to them.

Personally, I really like their visualisation. Overlaying the flight data with precipitation and cloud cover look fantastic.

The docker image mikenye/radarbox contains rbfeeder and all of its required prerequisites and libraries. This needs to run in conjunction with readsb (or another Beast provider).

Already running rbfeeder

You'll need your sharing key from your existing feeder.

To get your sharing key, log onto your feeder and issue the command:

rbfeeder --showkey --no-start

New to rbfeeder

If you're already running rbfeeder and you've followed the steps in the previous command, you can skip this section.

You'll need a sharing key. To get one, you can temporarily run the container, to allow it to communicate with the RadarBox servers generate a new sharing key.

Run the command:

timeout 300s docker run \
    --rm \
    -it \
    -e BEASTHOST=YOURBEASTHOST \
    -e LAT=YOURLATITUDE \
    -e LONG=YOURLONGITUDE \
    -e ALT=YOURALTITUDE \
    mikenye/radarbox

Be sure to change the following:

  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude of your antenna in metres
  • Replace YOURBEASTHOST with the IP address of your readsb instance (you may need to include --network=<network>, you can find your ADSB network with docker network ls)

The command will run the container for 5 minutes, which should be ample time for the container to receive a sharing key.

For example:

$ timeout 300s docker run --rm -it -e BEASTHOST=192.168.69.35 -e LAT=-31.897798 -e LONG=115.92858 -e ALT=90m mikenye/radarbox
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-rbfeeder: executing...
WARNING: TZ environment variable not set

WARNING: SHARING_KEY environment variable was not set!
Please make sure you note down the key generated.
Pass the key as environment var SHARING_KEY on next launch!

[cont-init.d] 01-rbfeeder: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
[rbfeeder] [2020-04-03 08:57:39]  Starting RBFeeder Version 0.2.6 (build 20180313082038)
[rbfeeder] [2020-04-03 08:57:39]  Using configuration file: /etc/rbfeeder.ini
[rbfeeder] [2020-04-03 08:57:39]  Network-mode enabled.
[rbfeeder] [2020-04-03 08:57:39]                Remote host to fetch data: 172.99.7.4
[rbfeeder] [2020-04-03 08:57:39]                Remote port: 30005
[rbfeeder] [2020-04-03 08:57:39]                Remote protocol: BEAST
[rbfeeder] [2020-04-03 08:57:39]  System: raspberry
[rbfeeder] [2020-04-03 08:57:39]  Start date/time: 2020-04-03 08:57:39
[rbfeeder] [2020-04-03 08:57:39]  Socket for ANRB created. Waiting for connections on port 32088
[rbfeeder] [2020-04-03 08:57:41]  Connection established.
[rbfeeder] [2020-04-03 08:57:41]  Empty sharing key. We will try to create a new one for you!
[rbfeeder] [2020-04-03 08:57:42]  Your new key is g45643ab345af3c5d5g923a99ffc0de9. Please save this key for future use. You will have to know this key to link this receiver to your account in RadarBox24.com. This key is also saved in configuration file (/etc/rbfeeder.ini)

As you can see from the output above, the sharing key given to us from FlightAware is g45643ab345af3c5d5g923a99ffc0de9.

You should now claim your receiver:

  1. Go to https://www.radarbox.com/
  2. Create an account or sign in
  3. Claim your receiver by visiting https://www.radarbox.com/raspberry-pi/claim and following the instructions

Deploying rbfeeder container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  rbfeeder:
    image: mikenye/radarbox:latest
    tty: true
    container_name: rbfeeder
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE
      - SHARING_KEY=YOURSHARINGKEY
    networks:
      - adsbnet

Be sure to change the following:

  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude of your antenna in metres
  • Replace YOURSHARINGKEY with the fr24key from your original receiver or the one you generated in the previous step.

So, assuming:

  • Our latitude is -33.33333, longitude is 111.11111 and altitude is 90m
  • Our timezone is Australia/Perth
  • Our sharing key is g45643ab345af3c5d5g923a99ffc0de9

...then our docker-compose.yml file would be appended with the following:

  rbfeeder:
    image: mikenye/radarbox:latest
    tty: true
    container_name: rbfeeder
    restart: always
    environment:
      - TZ=Australia/Perth
      - BEASTHOST=readsb
      - LAT=-33.33333
      - LONG=111.11111
      - ALT=90
      - SHARING_KEY=g45643ab345af3c5d5g923a99ffc0de9
    networks:
      - adsbnet

To explain what's going on in this file:

  • We're creating a container called rbfeeder, from the image mikenye/radarbox:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333, LONG=111.11111 and ALT=90 to specify our antenna location.
    • SHARING_KEY=g45643ab345af3c5d5g923a99ffc0de9 to specify our sharing key.

Once the file is created, issue the command docker-compose up -d to bring up the new rbfeeder container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
fr24 is up-to-date
Creating rbfeeder

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

rbfeeder          | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
rbfeeder          | [s6-init] ensuring user provided files have correct perms...exited 0.
rbfeeder          | [fix-attrs.d] applying ownership & permissions fixes...
rbfeeder          | [fix-attrs.d] done.
rbfeeder          | [cont-init.d] executing container initialization scripts...
rbfeeder          | [cont-init.d] 01-rbfeeder: executing...
rbfeeder          | [cont-init.d] 01-rbfeeder: exited 0.
rbfeeder          | [cont-init.d] done.
rbfeeder          | [services.d] starting services
rbfeeder          | [mlat-client] Delaying mlat-client startup until rbfeeder receives station sn...
rbfeeder          | [services.d] done.
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Starting RBFeeder Version 0.2.6 (build 20180313082038)
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Using configuration file: /etc/rbfeeder.ini
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Network-mode enabled.
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]            Remote host to fetch data: 172.99.7.4
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]            Remote port: 30005
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]            Remote protocol: BEAST
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  System: raspberry
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Start date/time: 2020-04-06 05:12:28
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Socket for ANRB created. Waiting for connections on port 32088
rbfeeder          | [rbfeeder] [2020-04-06 05:12:29]  Connection established.
rbfeeder          | [rbfeeder] [2020-04-06 05:12:40]  Could not start connection. Timeout.
rbfeeder          | [mlat-client] Delaying mlat-client startup until rbfeeder receives station sn...
rbfeeder          | [rbfeeder] [2020-04-06 05:12:58]  ******** Statistics updated every 30 seconds ********
rbfeeder          | [rbfeeder] [2020-04-06 05:12:58]  Packets sent in the last 30 seconds: 0, Total packets sent since startup: 0
rbfeeder          | [rbfeeder] [2020-04-06 05:13:10]  Connection established.
rbfeeder          | [rbfeeder] [2020-04-06 05:13:11]  Connection with RadarBox24 server OK! Key accepted by server.
rbfeeder          | [mlat-client] Mon Apr  6 05:13:28 2020 mlat-client 0.2.11 starting up
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Connected to multilateration server at mlat1.rb24.com:40900, handshaking
rbfeeder          | [rbfeeder] [2020-04-06 05:13:29]  ******** Statistics updated every 30 seconds ********
rbfeeder          | [rbfeeder] [2020-04-06 05:13:29]  Packets sent in the last 30 seconds: 87, Total packets sent since startup: 87
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Server says:
rbfeeder          | [mlat-client]
rbfeeder          | [mlat-client]         AirNAv Server
rbfeeder          | [mlat-client]
rbfeeder          | [mlat-client]         The multilateration server source code is available under
rbfeeder          | [mlat-client]         the terms of the Affero GPL (v3 or later). You may obtain
rbfeeder          | [mlat-client]         a copy of this server's source code at the following
rbfeeder          | [mlat-client]         location: https://github.com/mutability/mlat-server
rbfeeder          | [mlat-client]
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Handshake complete.
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020   Compression:       zlib2
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020   UDP transport:     disabled
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020   Split sync:        disabled
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Input connected to readsb:30005
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Input format changed to BEAST, 12MHz clock
rbfeeder          | [rbfeeder] [2020-04-06 05:14:00]  ******** Statistics updated every 30 seconds ********
rbfeeder          | [rbfeeder] [2020-04-06 05:14:00]  Packets sent in the last 30 seconds: 148, Total packets sent since startup: 235

We can see our container running with the command docker ps.

Once running, you can visit the RadarBox website, and go to "Account" > "Stations" and click your station to see your live data.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

It is worth noting that rbfeeder is extremely noisy when it comes to logging. If you haven't set up Docker log rotation as outlined earlier, consider doing this, lest your /var/lib/docker become full.

Feeding PlaneFinder

pfclient is a PlaneFinder client program to transmit ADS-B and Mode S data to the commercial entity PlaneFinder.

In exchange for your data, PlaneFinder will give you a "Gifted Sharer Subscription". If this is something of interest, you may wish to feed your data to them.

The docker image mikenye/planefinder contains pfclient and all of its required prerequisites and libraries. This needs to run in conjunction with readsb (or another Beast provider).

Already running pfclient

You'll need your share code from your existing feeder.

To get your share code, log into your planefinder.net account, and go to "Your Receivers". Your share code will be listed next to your existing receiver.

You will need to make sure your existing receiver is shutdown prior to continuing.

New to pfclient

If you're already running pfclient and you've followed the steps in the previous command, you can skip this section.

You'll need a share code. In order to obtain a PlaneFinder Share Code, we will start a temporary container running pfclient, which will run through a configuration wizard and generate a share code.

Run the command:

docker run \
    --rm \
    -it \
    --name pfclient_temp \
    --entrypoint pfclient \
    -p 30053:30053 \
    mikenye/planefinder

Once the container has started, you should see a message such as:

2020-04-11 06:45:25.823307 [-] We were unable to locate a configuration file and have entered configuration mode by default. Please visit: http://172.22.7.12:30053 to complete configuration.

At this point, open a web browser and go to http://dockerhost:30053. Replace dockerhost with the IP address of your host running Docker. You won't be able to use the URL given in the log output, as the IP address given will be the private IP of the docker container.

In your browser, go through the configuration wizard. When finished, you'll be given a PlaneFinder Share Code. Save this in safe place.

You can now kill the container by pressing CTRL-C.

You should now claim your receiver:

  1. Go to https://www.planefinder.net/
  2. Create an account and/or sign in
  3. Go to "Account" > "Manage Receivers"
  4. Click "Add receiver" and enter your share code when prompted

Deploying pfclient container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  pfclient:
    image: mikenye/planefinder:latest
    tty: true
    container_name: pfclient
    restart: always
    ports:
      - 30053:30053
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - SHARECODE=YOURSHARECODE
    networks:
      - adsbnet

Be sure to change the following:

  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude of your antenna in metres
  • Replace YOURSHARECODE with the share code from your original receiver or the one you generated in the previous step.

So, assuming:

  • Our latitude is -33.33333, longitude is 111.11111 and altitude is 90m
  • Our timezone is Australia/Perth
  • Our share code is zg84632abhf231

...then our docker-compose.yml file would be appended with the following:

  pfclient:
    image: mikenye/planefinder:latest
    tty: true
    container_name: pfclient
    restart: always
    ports:
      - 30053:30053
    environment:
      - TZ=Australia/Perth
      - BEASTHOST=readsb
      - LAT=-33.33333
      - LONG=111.11111
      - SHARECODE=zg84632abhf231
    networks:
      - adsbnet

To explain what's going on in this file:

  • We're creating a container called pfclient, from the image mikenye/planefeeder:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333 and LONG=111.11111 to specify our antenna location.
    • SHARECODE=zg84632abhf231 to specify our sharing key.

Once the file is created, issue the command docker-compose up -d to bring up the new pfclient container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
fr24 is up-to-date
rbfeeder is up-to-date
Creating pfclient

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

pfclient          | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
pfclient          | [s6-init] ensuring user provided files have correct perms...exited 0.
pfclient          | [fix-attrs.d] applying ownership & permissions fixes...
pfclient          | [fix-attrs.d] done.
pfclient          | [cont-init.d] executing container initialization scripts...
pfclient          | [cont-init.d] 01-pfclient: executing...
pfclient          | [cont-init.d] 01-pfclient: exited 0.
pfclient          | [cont-init.d] done.
pfclient          | [services.d] starting services
pfclient          | [services.d] done.
pfclient          | 2020-04-11 09:14:33.361261 [-] pfclient (4.1.1 i386) started with the following options:
pfclient          | 2020-04-11 09:14:33.361432 [-]      connection_type = 1
pfclient          | 2020-04-11 09:14:33.361437 [-]      tcp_address = readsb
pfclient          | 2020-04-11 09:14:33.361440 [-]      tcp_port = 30005
pfclient          | 2020-04-11 09:14:33.361442 [-]      data_format = 1
pfclient          | 2020-04-11 09:14:33.361445 [-]      aircraft_timeout = 30
pfclient          | 2020-04-11 09:14:33.361448 [-]      select_timeout = 10
pfclient          | 2020-04-11 09:14:33.361450 [-]      web_server_port = 30053
pfclient          | 2020-04-11 09:14:33.361454 [-]      user_latitude = -33.33333
pfclient          | 2020-04-11 09:14:33.361458 [-]      user_longitude = 111.11111
pfclient          | 2020-04-11 09:14:33.361539 [V] Performing NTP sync (1.planefinder.pool.ntp.org)...
pfclient          | 2020-04-11 09:14:33.361679 [-] Web server is now listening on: http://172.99.7.64:30053
pfclient          | 2020-04-11 09:14:33.361698 [-] Echo port is now listening on: 172.99.7.64:30054
pfclient          | 2020-04-11 09:14:33.362179 [-] TCP connection established: readsb:30005
pfclient          | 2020-04-11 09:14:33.723215 [V] NTP sync succeeded with settings:
pfclient          | 2020-04-11 09:14:33.723269 [V]      Stratum: 3
pfclient          | 2020-04-11 09:14:33.723287 [V]      System clock time: 1586596473.7232
pfclient          | 2020-04-11 09:14:33.723299 [V]      Corrected clock time: 1586596473.7181
pfclient          | 2020-04-11 09:14:33.723310 [V]      NTP offset: -0.0052s
pfclient          | 2020-04-11 09:15:38.239652 [-] User location has been verified.
pfclient          | 2020-04-11 09:16:23.809962 [-] Successfully sent 46 aircraft updates across 10 packets (8.00KB)
pfclient          | 2020-04-11 09:18:14.117198 [-] Successfully sent 57 aircraft updates across 10 packets (9.00KB)
pfclient          | 2020-04-11 09:20:04.389081 [-] Successfully sent 53 aircraft updates across 10 packets (8.00KB)

We can see our container running with the command docker ps.

Once running, you can:

  • Go to http://dockerhost:30053 to see your live data and statistics
  • Visit the PlaneFinder website, and go to "Account" > "Manage Receivers" and click your receiver to see your live data and statistics

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Clone this wiki locally