So you came here expecting docker-shipxplorer
? As of March 15, 2024 (the Ides of March!), the docker-shipxplorer
repo has been renamed to docker-shipfeeder
. The container can do so much more than just feeding ShipXplorer, and the new name covers the scope of what we're doing much better!
We're still enthusiastic feeders of AIS data to AirNav's ShipXplorer, and the amount of support that company has provided to the community is much appreciated. No changes there!
The newly updated container now also allows you to much easier configure feeding the other aggregators, see the Feeding AIS Aggregator Services section!
In adding all these improvements, we didn't forget our current users: the container is fully backwards compatible with the settings and environment variables you are already using. So no change is needed, unless you want to. We're also automatically producing two container images in parallel - they are exactly the same except for their names: ghcr.io/sdr-enthusiasts/docker-shipfeeder
(new!) and ghcr.io/sdr-enthusiasts/shipxplorer
(legacy).
If you need help, feel free to chat with us at the Discord server that is linked elsewhere in this Readme.
- sdr-enthusiasts/docker-shipfeeder
- What's New
- Table of Contents
- Prerequisites
- Multi Architecture Support
- Up-and-Running with Docker Compose
- Runtime Environment Variables
- Feeding AIS Aggregator Services
- Adding an
About
Page to the AIS-Catcher Website - Logging
- AIS-Catcher Web Plugin Support and AIS-Catcher Persistency
- Additional Statistics Dashboard with Prometheus and Grafana
- Configuring 2 SDRs for Reception on Channels AB and CD
- Aggregating multiple instances of the container
- Hardware requirements
- Getting Help
- Acknowledgements
- License
Docker container for feeding many AIS aggregators, showing a local map with ships heard, etc. The container uses AIS-Catcher and also includes AirNav ShipXplorer's sxfeeder
. Builds and runs on arm64
, armv7/armhf
, and amd64/x86
.
We expect you to have the following:
- a piece of hardware that runs Linux. The prebuilt containers support
armhf
,arm64
, andamd64
. Systems with those architectures include Raspberry Pi 3B+, 4, and Linux PCs with Ubuntu. - a dedicated RTL-SDR dongle that can receive at 160 MHz, with an appropriate antenna
- Docker must be installed on your system. If you don't know how to do that, please read here.
- Some basic knowledge on how to use Linux and how to configure docker containers with
docker-compose
.
Currently, this image should pull and run on the following architectures:
arm32v7
,armv7l
,armhf
: ARMv7 32-bit (Odroid HC1/HC2/XU4, RPi 2/3/4 32-bit)arm64
,aarch64
: ARMv8 64-bit (RPi 4 64-bit OSes)amd64
,x86_64
: X86 64-bit Linux (Linux PC)
Other architectures (Windows, Mac) are not currently supported, but feel free to see if the container builds and runs for these. In theory, it should work, but I don't have the time nor inclination to test it.
You can find these as files here: docker-compose.yml
example; .env
example
<‐‐ Click the arrow to see the docker-compose.yml
and .env
examples
version: '3.8'
services:
shipfeeder:
image: ghcr.io/sdr-enthusiasts/docker-shipfeeder
container_name: shipfeeder
hostname: shipfeeder
restart: always
environment:
# general parameters:
- VERBOSE_LOGGING=
# ais-catcher general and website related parameters
- AISCATCHER_EXTRA_OPTIONS=${SX_EXTRA_OPTIONS}
- STATION_NAME=${STATION_NAME}
- STATION_HISTORY=3600
- BACKUP_INTERVAL=5
- FEEDER_LONG=${FEEDER_LONG}
- FEEDER_LAT=${FEEDER_LAT}
- SITESHOW=on
- PROMETHEUS_ENABLE=on
- REALTIME=on
# ais-catcher receiver-related parameters
- RTLSDR_DEVICE_SERIAL=${RTLSDR_DEVICE_SERIAL}
- RTLSDR_DEVICE_GAIN=${RTLSDR_DEVICE_GAIN}
- RTLSDR_DEVICE_PPM=${RTLSDR_DEVICE_PPM}
- RTLSDR_DEVICE_BANDWIDTH=${RTLSDR_DEVICE_BANDWIDTH}
- AISCATCHER_DECODER_AFC_WIDE=${AISCATCHER_DECODER_AFC_WIDE}
# aggregrators-related parameters
- AIRFRAMES_STATION_ID=${AIRFRAMES_STATION_ID}
- AISCATCHER_FEEDER_KEY=${AISCATCHER_FEEDER_KEY}
- AISHUB_UDP_PORT=${AISHUB_UDP_PORT}
- APRSFI_FEEDER_KEY=${APRSFI_FEEDER_KEY}
- BOATBEACON_SHAREDATA=${BOATBEACON_SHAREDATA}
- HPRADAR_UDP_PORT=${HPRADAR_UDP_PORT}
- MARINETRAFFIC_UDP_PORT=${MARINETRAFFIC_UDP_PORT}
- MYSHIPTRACKING_UDP_PORT=${MYSHIPTRACKING_UDP_PORT}
- RADARVIRTUEL_FEEDER_KEY=${RADARVIRTUEL_FEEDER_KEY}
- RADARVIRTUEL_STATION_ID=${RADARVIRTUEL_STATION_ID}
- SHIPFINDER_SHAREDATA=${SHIPFINDER_SHAREDATA}
- SHIPPINGEXPLORER_UDP_PORT=${SHIPPINGEXPLORER_UDP_PORT}
- SHIPXPLORER_SHARING_KEY=${SHIPXPLORER_SHARING_KEY}
- SHIPXPLORER_SERIAL_NUMBER=${SHIPXPLORER_SERIAL_NUMBER}
- VESSELFINDER_UDP_PORT=${VESSELFINDER_UDP_PORT}
- VESSELTRACKER_UDP_PORT=${VESSELTRACKER_UDP_PORT}
- UDP_FEEDS=${SX_UDP_FEEDS}
# incoming UDP data related parameters:
- AISCATCHER_UDP_INPUTS=${AISCATCHER_UDP_INPUTS}
ports:
- 90:80
- 9988:9988/udp
device_cgroup_rules:
- 'c 189:* rwm'
tmpfs:
- /tmp
volumes:
- "/etc/localtime:/etc/localtime:ro"
- "/etc/timezone:/etc/timezone:ro"
- "/opt/ais/shipxplorer/data:/data"
- /dev:/dev:rw
Example accompanying .env
file:
# ShipFeeder receiver and webpage related parameters:
FEEDER_LAT=xx.xxxxxx
FEEDER_LONG=yy.yyyyyy
RTLSDR_DEVICE_SERIAL=DEVICE-SERIAL
RTLSDR_DEVICE_GAIN=xxx
RTLSDR_DEVICE_PPM=xxx
AISCATCHER_DECODER_AFC_WIDE=on
STATION_NAME=My Station Name
#
# keys and params for aggregators:
# If you aren't feeding a specific aggregator, leave the value EMPTY or remove the parameter
AIRFRAMES_STATION_ID=XX-XXXXXXX-AIS
AISCATCHER_FEEDER_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AISHUB_UDP_PORT=xxxx
APRSFI_FEEDER_KEY=xxxxxxx
APRSFI_STATION_ID=MYCALL
BOATBEACON_SHAREDATA=true
HPRADAR_UDP_PORT=xxxx
MARINETRAFFIC_UDP_PORT=xxxxx
MYSHIPTRACKING_UDP_PORT=xxxxx
RADARVIRTUEL_FEEDER_KEY=xxxxxxxxx
RADARVIRTUEL_STATION_ID=xx
SHIPFINDER_SHAREDATA=true
SHIPPINGEXPLORER_UDP_PORT=xxxxx
SHIPXPLORER_SHARING_KEY=xxxxxxxxxxxxxxxxxxx
SHIPXPLORER_SERIAL_NUMBER=SXTRPI00xxxx
VESSELFINDER_UDP_PORT=xxxx
VESSELTRACKER_UDP_PORT=xxxx
Replace these parameters with the appropriate values.
You can use rtl_test
to see which devices and device serials are connected to your machine, or rtl_eeprom
to rename the device's serial number.
Environment Variable | Purpose | Default value if omitted |
---|---|---|
RTLSDR_DEVICE_SERIAL |
Serial Number of your RTL-SDR dongle | Empty |
RTLSDR_DEVICE_GAIN |
SDR device gain. Can also be set to auto |
33 |
RTLSDR_DEVICE_PPM |
PPM deviation of your RTLSDR device | Empty |
RTLSDR_DEVICE_BANDWIDTH |
Channel bandwitdh of the receiver | 192K |
RTLSDR_DEVICE_BIASTEE |
If set to on , 1 , enabled , or yes , the bias-tee function of the RTLSDR device will be switched on |
Empty |
AISCATCHER_CHANNELS |
Channels flag for ais-catcher . Set to AB (receive on channel AB, default value if omitted), CD (receive on channel CD), or CD AB (receive on channel CD but forward this data to aggregators saying it's channel AB; this can be used to send channels CD data to aggregators that can't handle CD data) |
Empty (AB ) |
AISCATCHER_DECODER_MODEL |
Decoder model number for ais-catcher |
2 |
AISCATCHER_DECODER_AFC_WIDE |
-go AFC_WIDE flag for ais-catcher . Recommended to set to on |
on |
AISCATCHER_DECODER_FP_DS |
-go PF_DS flag for ais-catcher |
Empty |
AISCATCHER_DECODER_PS_EMA |
-go PS_EMA flag for ais-catcher |
Empty |
AISCATCHER_DECODER_SOXR |
-go SOXR flag for ais-catcher |
Empty |
AISCATCHER_DECODER_SRC |
-go SRC flag for ais-catcher |
Empty |
AISCATCHER_DECODER_DROOP |
-go DROOP flag for ais-catcher |
Empty |
AISCATCHER_UDP_INPUTS |
List of comma-separated hostname:port[:CHANNELS] combinations of external NMEA AIS data UDP sources. You can use this to feed data between ais-catcher or docker-shipfeeder instances. The :CHANNELS part is optional; channels AB will be used if omitted. ExamplesAISCATCHER_UDP_INPUTS=remotehost-1:9999:AB CD,remotehost-2:9988,remotehost-3:8899:CD |
Empty |
AISCATCHER_EXTRA_OPTIONS |
Any additional command line parameters you wish to pass to AIS-catcher |
Empty |
VERBOSE_LOGGING |
If set to a number (0 -5 ), it's set to the AIS-Catcher -o log level. Any other non-empty string corresponds to -o 2 . To silence AIS-Catcher logs, set this parameter to 0 |
2 (a summary is displayed every 60 seconds) |
If the AISCATCHER_CHANNELS
and AISCATCHER_DECODER_XXXX
parameters listed above are set, they will overwrite/remove any equivalent parameters added to the AISCATCHER_EXTRA_OPTIONS
parameter.
Environment Variable | Purpose | Default value if omitted |
---|---|---|
DISABLE_WEBSITE |
If set to true , the AIS-Catcher website will not be available |
false |
PLUGINS_FILE |
Load a file with custom javascript to override parts of the WebUI or add functionality. Map the container /data to any volume, place your file inside the volume and put the file name here (for example plugins.js ) |
Empty |
STYLES_FILE |
Load a file with custom css to override parts of the WebUI or add functionality. Map the container /data to any volume, place your file inside the volume and put the file name here (for example styles.css ) |
Empty |
STATION_NAME |
Station name displayed on stat web page | Empty |
STATION_LINK |
URL displayed on stat web page | Empty |
STATION_HISTORY |
The number of seconds of history that will be shown in plots on the website | 3600 |
BACKUP_INTERVAL |
How often a file with data statistics (aiscatcher.bin ) will be written to disk, in minutes. In order to make this backup persistent, make sure to map the /data directory to a volume. See example in docker-compose.yml. |
2880 (=2 days) |
BACKUP_RETENTION_TIME |
Time (in days) to keep backups of aiscatcher.bin and plugins. Note - this only affects the backups of these files and not the active aiscatcher.bin or active plugins. |
30 (days) |
SITESHOW |
If set to anything non-empty, it will show the station location as a dot on the map | Empty |
FEEDER_LAT or SXFEEDER_LAT (legacy) |
Used for calculating ship distances on web page | Empty |
FEEDER_LONG or SXFEEDER_LON (legacy) |
Used for calculating ship distances on web page | Empty |
DISABLE_SHOWLASTMSG |
If set to true , the last NMEA0182 message option won't be shown on the website. |
Empty, i.e., last message option is available on website |
PLUGIN_UPDATE_INTERVAL |
Optional. Set this to the interval (for example, 30 (secs) or 5m or 6h or 3d ) to check the AIS-Catcher github repository for updates to the JavaScript web plugins. Set to 0 or off to disable checking. |
6h |
REFRESHRATE |
Refresh rate of the vessel data on the web page, in msec. Larger numbers reduce web page traffic, which can become an issue if there are a large number of vessels | 2500 (msec) |
DISABLE_GEOJSON |
If set to true , no GeoJSON info will be available at http://my_aiscatcher/geojson. This is normally enabled if the parameter is omitted. |
Empty (GeoJSON is default enabled) |
This table shows which parameters to set and how to obtain credentials for a number of well-known AIS aggregators. A (partial) list of these aggregators and instructions on how to get a key or port for them can be found here
Name | Parameter | Default IP/DNS/URL | Feeding protocol: UDP/TCP/HTTP/Other |
How to register for a key or ID |
---|---|---|---|---|
ADSB-Network (RadarVirtuel) | RADARVIRTUEL_FEEDER_KEY (optional, value is lourd if omitted)RADARVIRTUEL_STATION_ID |
https://ais.adsbnetwork.com/ingester/insert/$RADARVIRTUEL_FEEDER_KEY | HTTP | Email support@adsbnetwork.com with your request to join. If you receive an ais-catcher string like this: -H http://ais.adsbnetwork.com/ingester/insert/lourd ID xx INTERVAL 5 RESPONSE off , then simply set RADARVIRTUEL_STATION_ID to xx and omit or leave blank the RADARVIRTUEL_FEEDER_KEY parameter |
Airframes | AIRFRAMES_STATION_ID |
http://feed.airframes.io:5599 | HTTP | No signup needed. AIRFRAMES_STATION_ID is a self-chosen ID that has the form of II-STATIONNAME-AIS , where II are the initials of the owner's name, and STATIONNAME is a self-chosen station name (A-Z, 0-9 only please) |
AIS-Catcher | AISCATCHER_SHAREDATA=true AISCATCHER_FEEDER_KEY |
Other | See Exchanging data with aiscatcher.org https://aiscatcher.org/#join. In the future, AISCatcher may provide you with an optional UUID that you can set in AISCATCHER_FEEDER_KEY |
|
AISHub | AISHUB_UDP_PORT |
data.aishub.net | UDP | https://www.aishub.net/join-us |
APRS.fi | APRSFI_FEEDER_KEY APRSFI_STATION_ID |
http://aprs.fi/jsonais/post/$APRS_FEEDER_KEY | HTTP | Get AIS Password (APRSFI_FEEDER_KEY ) at https://aprs.fi/?c=account. Use your Ham Radio callsign for APRSFI_STATION_ID . Both fields are mandatory. |
BoatBeacon | BOATBEACON_SHAREDATA=true |
boatbeaconapp.com:5322 | UDP | https://pocketmariner.com/ais-ship-tracking/cover-your-area/set-up-and-ais-shore-station/ - no keys or IDs are required |
HPRadar | HPRADAR_UDP_PORT |
aisfeed.hpradar.com | UDP | |
MarineTraffic | MARINETRAFFIC_UDP_PORT orMARINETRAFFIC_TCP_PORT |
5.9.207.224 | UDP / TCP | https://www.marinetraffic.com/en/join-us/cover-your-area Please use either the UDP option or the TCP option as instructed by MarineTraffic, but don't use both! |
MyShipTracking | MYSHIPTRACKING_UDP_PORT orMYSHIPTRACKING_TCP_PORT |
178.162.215.175 | UDP / TCP | https://www.myshiptracking.com/help-center/contributors/add-your-station By default, you should use UDP to feed, unless you are specifically asked to use TCP by the company. Do not use both! |
ShipFinder | SHIPFINDER_SHAREDATA=true |
ais.shipfinder.co.uk:4001 | UDP | https://shipfinder.co/about/coverage/ |
ShippingExplorer | SHIPPINGEXPLORER_UDP_PORT orSHIPPINGEXPLORER_TCP_PORT |
144.76.54.111 | UDP or TCP | Request UDP port at https://www.shippingexplorer.net/en/contact By default, you should use UDP to feed, unless you are specifically asked to use TCP by the company. Do not use both! |
ShipXplorer | SHIPXPLORER_SHARING_KEY or SHARING_KEY (legacy)SHIPXPLORER_SERIAL_NUMBER or SERIAL_NUMBER (legacy) |
Other | See Obtaining a ShipXplorer Sharing Key | |
ShipXplorer (alt. config with UDP) | SHIPXPLORER_UDP_PORT |
hub.shipxplorer.com | UDP | Alternative way to feed ShipXplorer via UDP instead of via a Sharing Key. Please use one or the other, but not both! Sign up at https://www.shipxplorer.com/addcoverage and select "I want to share with: NMEA over UDP" |
VesselFinder | VESSELFINDER_UDP_PORT orVESSELFINDER_TCP_PORT |
ais.vesselfinder.com | UDP / TCP | https://stations.vesselfinder.com/become-partner By default, you should use UDP to feed, unless you are specifically asked to use TCP by the company. Do not use both! |
VesselTracker | VESSELTRACKER_UDP_PORT orVESSELTRACKER_TCP_PORT |
83.220.137.136 | UDP or TCP | https://www.vesseltracker.com/en/static/antenna-partner.html By default, you should use UDP to feed, unless you are specifically asked to use TCP by the company |
Note: for all parameters SERVICE_UDP_PORT
(and similarly for SERVICE_TCP_PORT
where supported), you may use one of the following formats:
- SERVICE_UDP_PORT=1234
--> use UDP port 1234- SERVICE_UDP_PORT=hostname:1234
or- SERVICE_UDP_PORT=ip_addr:1234
--> use the hostname or ip address instead of the one indicated in the table, and UDP port 1234
For services that do no need any UDP ports or credentials, you can simply set - SERVICE_SHAREDATA=true
. However, if you want to use a non-default port and/or hostname/ip, you can set also SERVICE_UDP_PORT
(as shown above) for that service. Order of preference:
- if
SERVICE_UDP_PORT
is defined --> use this UDP port regardless of the value ofSERVICE_SHAREDATA
- if
SERVICE_SHAREDATA
is set totrue
andSERVICE_UDP_PORT
is not defined --> use the default UDP port to feedSERVICE
- if
SERVICE_TCP_PORT
is defined --> use this TCP port in addition to any UDP port (orSHAREDATA
setting). Warning - this may cause duplicate feeding to the aggregator
We decided to allow parallel feeding to UDP and TCP ports because some aggregators have asked our users to do this temporarily for testing. However, the user should take caution not to feed duplicate data to any aggregator unless the aggregator specifically requested this for testing purposes.
aiscatcher.org is an exchange of AIS NMEA data. If you share your data with this server, you automatically receive data about other ships in return. We recommend to switch this on for an optimal viewing experience.
You can enable it by simply adding the following to the environment section of your shipfeeder
service section in docker-compose.yml
. Note that the AISCATCHER_SHAREKEY
parameter is optional and will be ignored for now, pending implementation of this feature by AIS-Catcher.
- AISCATCHER_SHAREDATA=true
- AISCATCHER_SHAREKEY=xxxxxxxx
ATTENTION Raspberry Pi 5 users (only) should read Working around ShipXplorer issues on Raspberry Pi 5 before proceeding!
First-time users should obtain a ShipXplorer sharing key. In order to obtain a ShipXplorer sharing key, on the first run of the container, it will generate a sharing key and print this to the container log. If you can't find it, you can also copy and paste this command:
timeout 180s docker run \
--rm \
-it \
--entrypoint /usr/bin/get-creds \
ghcr.io/sdr-enthusiasts/docker-shipfeeder:latest
This will run the container for 3 minutes, allowing a sharing key to be generated. Shortly after, you will see something like this:
WARNING: SHARING_KEY or SERIAL_NUMBER environment variable was not set!
Please make sure you note down the keys generated and update your docker-compose.yml with these values.
Set environment var SHARING_KEY to the new key displayed below - this is the long hex number
Set environment var SERIAL_NUMBER to the Serial Number displayed below - this is the SXTRPIxxxxxx string
They must be set for this container to run.
Please set it and restart the container.
[2022-11-01 19:48:19] Your new key is f1xxxxxxxxxxxxxxxxxxxxxxxx57 and Serial Number (SN) is SXTRPIxxxxxx.
Please save this key for future use. You will have to know this key to link this receiver to your account
in https://www.shipxplorer.com/. This key is also saved in configuration file (/etc/sxfeeder.ini)
You can wait for the 3 minutes to pass, or you can press CTRL-C now to finish.
Take a note of the Sharing Key (f1...57
- yours will be a different number) and the Serial Number (SXTRPIxxxxxx
), and add these to the SHIPXPLORER_SHARING_KEY
and SHIPXPLORER_SERIAL_NUMBER
parameters of your docker-compose.yml
file.
If you're not a first time user and are migrating from another installation, you can retrieve your sharing key by doing this:
- SSH onto your existing receiver and run the command
cat /etc/sxfeeder.ini
The key
and sn
lines show your current credentials
Once your container is up and running, you should claim your receiver.
- Go to https://www.shipxplorer.com
- Create an account or sign in
- Claim your receiver by visiting https://www.shipxplorer.com/addcoverage and following the instructions
Note - you will need your SHARING_KEY
and the location of your feeder (coordinates or pick on map). As of now, it appears that you don't need your SN or Public IP address.
sxfeeder
is the binary component that is used to feed data to ShipXplorer. Normally, you don't have to interact with it, but exceptional circumstances may arise where you would like to add additional command line parameters to this program. You can do so, by adding them as follows:
Environment Variable | Purpose | Default value if omitted |
---|---|---|
SXFEEDER_EXTRA_OPTIONS |
Any additional command line parameters you wish to pass to sxfeeder |
Empty |
The sxfeeder
binary effectively greps for serial\t\t:
in your /proc/cpuinfo
file, to determine the RPi's serial number.
For systems that don't have a CPU serial number in /proc/cpuinfo
, we can "fudge" this by generating a replacement cpuinfo
file with a random serial number. To do this, copy and paste the following on your host machine:
sudo mkdir -m777 -p /opt/shipfeeder/cpuinfo
sudo install -m 666 /proc/cpuinfo /opt/shipfeeder/cpuinfo/
echo -e "serial\t\t: $(hexdump -n 8 -e '4/4 "%08X" 1 "\n"' /dev/urandom | tr '[:upper:]' '[:lower:]')" >> /opt/shipfeeder/cpuinfo/cpuinfo
You can now map this file into your container:
- If using docker run, simply add
-v /opt/shipfeeder/cpuinfo/cpuinfo:/proc/cpuinfo
to your command. - If using docker-compose, add the following to the
volumes:
section of your shipfeeder container definition:
- /opt/shipfeeder/cpuinfo/cpuinfo:/proc/cpuinfo
If you want to feed and additional AIS aggregator that uses a hostname/UDP port that is not listed above, then simply add a comma separated list of hostnames/ip addresses and UDP ports to the UDP_FEEDS
parameter. Format: UDP_FEEDS=domain1.com:port1[:params],domain2,com:port2[:params],...
For example:
- UDP_FEEDS=1.2.3.4:9999,ais.aggregator.org:1234
If you want to feed and additional AIS aggregator that uses a hostname/TCP port that is not listed above, then simply add a comma separated list of hostnames/ip addresses and UDP ports to the TCP_FEEDS
parameter. Format: TCP_FEEDS=domain1.com:port1[:params],domain2,com:port2[:params],...
For example:
- TCP_FEEDS=1.2.3.4:8888,ais.aggregator.org:4321
To feed additional AIS aggregators that are not listed above using HTTP, you first need to create an AIS feeder account at that service. They will provide you with a URL and any additional parameters you need to configure AIS-Catcher. For example:
- AISCATCHER_EXTRA_OPTIONS=-H http://1.2.3.4/test ID my_station_name INTERVAL 30 RESPONSE off
Note: if you want to feed multiple HTTP aggregators, you can simply append each feeder string to the AISCATCHER_EXTRA_OPTIONS
variable with a space in between them. For example:
- AISCATCHER_EXTRA_OPTIONS=-H http://5.6.7.8/test/post/aBcDeFgHiJkL ID MYSTATION PROTOCOL aprs INTERVAL 30 RESPONSE off -H http://1.2.3.4/test ID my_station_name INTERVAL 30 RESPONSE off JSON on
You can add an About page to the AIS-Catcher Website by placing a file called about.md
in the /data
directory of the container. If you mapped this directory to a volume as shown in the example, the file as seen from the host system would be /opt/ais/shipfeeder/about.md
.
You can format the text in this file using Markdown.
- All processes are logged to the container's stdout, and can be viewed with
docker logs [-f] container
.
We recommend mapping a volume (as shown in the sample docker-compose.yml
file in this repo) to the /data
directory. This will ensure that AIS-Catcher data will persist across restarts and container recreation.
Web Plugins for AIS-Catcher can be placed in the /data/plugins
directory.
See this readme for information on how to set up and configure a Grafana stats dashboard for use with shipfeeder. Make sure to set this parameter to enable Prometheus data for the container:
Environment Variable | Purpose | Default value if omitted |
---|---|---|
PROMETHEUS_ENABLE |
If set to true , enables Prometheus data at /metrics on the webserver. |
Empty (disabled) |
If you want shipfeeder
to use 2 SDRs to listen to AIS Channels AB and CD at the same time, you can do the following
- Configure your first SDR (for use with channels AB) via the "normal"
RTLSDR_DEVICE_XXXX
parameters - Configure the second SDR using the
AISCATCHER_EXTRA_OPTIONS
parameter as follows (replaceSDR2-SERIAL
with the Serial Number of your second SDR):
- AISCATCHER_EXTRA_OPTIONS=-d SDR2-SERIAL -p 2 -a 192K -c CD -gr tuner auto rtlagc ON -v 60
- Subsequently, you can also add separate web pages for each SDR individually. The "normal" web interface on port
80
will show the combined receivers, while the following adds new web interfaces on ports81
for your Channels AB receiver, and on port82
for your Channels CD receiver. You can add this to the end of theAISCATCHER_EXTRA_OPTIONS
parameter, replacingSDR1_SERIAL
andSDR2_SERIAL
with the two serial IDs of the SDRs, and adjusting the other parameters as appropriate:
- AISCATCHER_EXTRA_OPTIONS=... -N 81 GROUPS_IN 1 STATION SDR1-SERIAL FILE /data/aiscatcher-ab.bin PLUGIN_DIR /data/plugins BACKUP 5 HISTORY 3600 STATION_LINK https://my.ais-station.com LAT xx.xxxx LON yy.yyyy SHARE_LOC on MESSAGE on REALTIME on -N 82 GROUPS_IN 2 STATION SDR2_SERIAL FILE /data/aiscatcher-cd.bin PLUGIN_DIR /data/plugins BACKUP 5 HISTORY 3600 STATION_LINK https://my.ais-station.com LAT xx.xxxx LON yy.yyyy SHARE_LOC on MESSAGE on REALTIME on
Sometimes it's convenient to aggregate the data of multiple instances of the container into a single one, and then feed the AIS aggregators from this "central" instance. An example of this is when you have a SDR receiving from channels AB in one instance, and a SDR receiving from channels CD in a separate instance on another machine. (If you have both SDRs on the same machine, you can use a single container instance for both of them as described above). In our case, you'd want to send the data from channels CD to the instance that receives channels AB, and then use that machine to disperse the data to the various services, show its webpage, etc.
Do the following. We are assuming that the hostname/container name for the instance receiving channels AB is shipfeeder_ab
and the hostname/container name for the instance receiving channels CD is shipfeeder_cd
. Your names may vary.
- In the section of the
docker-compose.yml
file forshipfeeder_cd
, make sure to add the following to theUDP_FEEDS
parameter. Make sure that you replacetarget_machine
with the IP or hostname of the machine whereshipfeeder_ab
runs:
- UDP_FEEDS=.....;target_machine:9988
- In the section of the
docker-compose.yml
file forshipfeeder_ab
, make sure to add the following to theAISCATCHER_UDP_INPUTS
parameter. (DO NOT USElocalhost
or127.0.0.1
- that won't work):
- AISCATCHER_UDP_INPUTS=shipfeeder_cd:9988:AB CD
- In addition, to the same section of the
docker-compose.yml
file forshipfeeder_cd
, make sure to forward the UPD port to the container:
ports:
[...]
- 9988:9988/udp
Once you have done this, and after you recreate the containers, the shipfeeder_cd
instance will now forward its data to shipfeeder_ab
, and shipfeeder_ab
will aggregate this data, display it on the AIS-Catcher map and tables, and forward it to any service you may have configured for it.
AIS data is transmitted in the 160 MHz band, for which you'd need a suitable antenna. Note -- ADSB/UAT antennas will definitely not work!
You would need a RTL-SDR dongle, potentially with an LNA, and potentially with a filter. The filter must be dedicated to the 160 MHz band. Dongles with built-in filters for the ADSB or UAT bands won't work.
Last - the software will run on a Raspberry Pi 3B+ or 4, with Raspberry Pi OS, Ubuntu, or a similar Debian-based operating system. It will also run on X86 (Linux PC) systems with Ubuntu. The prebuilt Docker container will work on armhf
/arm64
(aarch64
) /x86_64
(amd64
) architectures. You may be able to build containers for other systems, but for that you're on your own.
If you use ShipXplorer as recommended in Configuring feeding to ShipXplorer, the container internally uses a binary called sxfeeder
to send data to the ShipXplorer service. This binary is provided as closed-source by AirNav (the company that operates ShipXplorer) and is only available in armhf
(32-bits) format using 4kb kernel pages. This will work well on Raspberry Pi 3B+, 4B, and other ARM-based systems that use either 32-bits or 64-bits Debian Linux with a 4kb kernel page size.
Debian Linux for Raspberry Pi 5 uses by default a kernel with 16kb page sizes, and this is not compatible with the sxfeeder
binary. You will see this in your container logs:
2024-05-23T23:15:48.998327000Z [2024-05-24 01:15:48.998][sxfeeder] Starting: /usr/bin/sxfeeder
2024-05-23T23:15:49.003069000Z [2024-05-24 01:15:49.002][sxfeeder] FATAL: sxfeeder cannot be run natively, and QEMU is not available. You cannot use this container
2024-05-23T23:15:49.004680000Z [2024-05-24 01:15:49.004][sxfeeder] FATAL: on this system / architecture. Feel free to file an issue at https://github.com/sdr-enthusiasts/docker-shipxplorer/issues
2024-05-23T23:15:49.006086000Z [2024-05-24 01:15:49.005][sxfeeder] FATAL: Cannot initiate feeder to ShipXplorer.
You can check your kernel page size with this command: getconf PAGE_SIZE
. If the value returned is 4096, then all is good. If it is something else (for example 16384 for 16kb page size), you will need to implement one of the following work-arounds. You should implement either of them; it's not necessary to implement both:
-
Add the following to
/boot/firmware/config.txt
(Debian 12 Bookworm or later) or/boot/config.txt
(Debian 11 Bullseye or earlier) to use a kernel with page size of 4kb. This will make CPU use across your Raspberry Pi 5 slightly less efficient, but it will solve the issue for many software packages that have the same issue. After changing this, you must reboot your system for it to take effect:kernel=kernel8.img
-
Feed ShipXplorer with UDP instead of with a Sharing Key. To do this:
- Browse to https://www.shipxplorer.com/addcoverage and select "I want to share with: NMEA over UDP"
- Follow the instructions until you are issued a hostname and UDP port number
- set this environment variable in your
docker-compose.yml
file:SHIPXPLORER_UDP_PORT=portnumber
(replaceportnumber
with the UDP port you were assigned) and removeSHIPXPLORER_SHARING_KEY
and/orSHARING_KEY
from your configuration - recreate and restart the container with
docker compose up -d
You can log an issue on the project's GitHub.
I also have a Discord channel, feel free to join and converse.
This effort wouldn't exist without much help and advice of the following individuals:
- JvdE-Github, who created the excellent
ais-catcher
package which forms the basis of this container - Wiedehopf without whose advice we'd all still live in the stone age
- John Norrbin for his ideas, testing, feature requests, more testing, nagging, pushing, prodding, and overall efforts to make this a high quality container and for the USB "hotplug" configuration
- The community at the SDR-Enthusiasts Discord Server for helping out, testing, asking questions, and generally driving to make this a better productn
- Pete who provided access and major help testing new features
Copyright (C) 2022-2024, Ramon F. Kolb (kx1t)
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.