How to build a Raspberry Pi APRS Tracker using Dire Wolf

🗓 Posted


This is a follow up to my last post about getting my Amateur Radio Basic Qualification (with Honours) and being interested in APRS. Since then, I’ve made some progress in my ham radio journey and setup my own APRS tracker that I run in my truck! This allows me to go explore our backcountry roads without fear that I will get lost.

What lies beyond is mostly a brain dump of notes I made over the course of putting this project together so that in the future I can refer back to it when I forget some things about the setup. I’m hoping that it helps you when setting up your own APRS tracker using some open-source software called Dire Wolf and some other relatively inexpensive hardware.

It’s worth noting that this post does not cover any of the hardware setup required with a VHF radio, antenna, power requirements, etc.; In the future I may put together a part two post outlining my setup and how I have everything configured.


DigiRig USB Audio device

DigiRig USB Audio device

There are some things you need to get started:

  • A Raspberry Pi 3 B+ (or newer, it’s what I had on hand). You may be able to accomplish this with a lower-powered Raspberry Pi device, like a Zero W, but your mileage may vary.
  • A Baofeng UV-5R or other VHF (2 meter, 144MHz band) radio
  • A DigiRig v1.9 all-in-one audio device to receive and transmit audio to and from your radio.
    • Alternatively you could build your own with a CM108-based audio device. The upside of using the DigiRig is that it can also control some radios using the CAT interface over a serial connection (I won’t get into how that works in this post).
      • 3.5mm headphone/microphone audo splitter to get the audio and microphone into the Raspberry Pi if building your own cable.
      • A PTT-control circuit for the Raspberry Pi to be able to trigger PTT if you don’t go with the DigiRig above. It is possible to build your own using a 5V optocoupler which I have done with good success.
  • USB GPS device — practically any USB GPS device should work but this is the one I purchased and I can confirm works for this project (with a caveat).

Install OS Dependencies #

The setup for this build assumes the use of a Debian-based OS, in my case I use Ubuntu 22.04 Server.

sudo apt-get install -y vim git gcc gpsd gpsd-clients g++ make cmake ntp screen \
  avahi-daemon libasound2-dev libudev-dev libavahi-client-dev libgps-dev

GPS config (for Dire Wolf) #

Create /etc/udev/rules.d/49-usb-gps.rules and add:

# Force USB to specific `tty` if more than one serial device present on system (GPS and DigiRig compete)
KERNEL=="ttyACM[0-9]*", SUBSYSTEM=="tty", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a7", SYMLINK="ttyGPS"

Edit /etc/default/gpsd to add:


After configuring the GPS dependencies, initialize the service with:

sudo systemctl enable gpsd
sudo systemctl start gpsd

Now’s a good time to upgrade gpsd to a version without a very worrisome bug. Follow the link and build gpsd from source.

To retain accurate time on the device when it loses power, as there is no CMOS battery on a Raspberry Pi or a continuous power supply and it will unlikely be connected to a time server over a network, we can run sudo vim /etc/ntp.conf to edit the NTP service config file to pull extremely accurate time from the GPS receiver instead:

server 4
fudge time1 0.340 refid GPS
server prefer
fudge refid GPS1

Install Dire Wolf #

From the DireWolf repository on Github:

Decoded Information from Radio Emissions for Windows Or Linux Fans #

In the early days of Amateur Packet Radio, it was necessary to use an expensive “Terminal Node Controller” (TNC) with specialized hardware. Those days are gone. You can now get better results at lower cost by connecting your radio to the “soundcard” interface of a computer and using software to decode the signals.

Dire Wolf uses the Raspberry Pi to encode and decode audio sent and received from the DigiRig. It can even sent CAT control commands to control your radio over USB if it is supported!

NOTE: On a MacBook with an M1 chip running macOS 13.3, I had to run brew install cmake portaudio as dependencies prior to running the build.

cd ~
git clone && cd direwolf
git checkout dev
mkdir build && cd build
cmake .. && make -j4 && sudo make install && make install-conf

Modify the script and append -l /var/log/direwolf to the commandline arguments variable. This gives us the ability to view the logs of the running direwolf process in one place.

Every once in awhile it’s good to update Dire Wolf with the latest changes and commits from the upstream dev branch. To do this, run git pull origin dev && cd build && sudo make install.

DigiRig config (for Dire Wolf) #

Create a shortcut for the Digirig USB device by creating /etc/udev/rules.d/85-usb-digirig.rules:

SUBSYSTEM=="tty", GROUP="dialout", MODE="0660", ATTRS{product}=="CP2102N USB to UART Bridge Controller", SYMLINK+="ttyDigiRig"

Don’t forget to run after the previous step:

sudo chmod 0644 /etc/udev/rules.d/85-usb-digirig.rules && sudo udevadm control --reload-rules && sudo reboot

Boot config (specific for rPi 3) #

Edit /boot/config.txt to modify the boot-time configuration for the DigiRig and GPS to play nice with USB stack:

dtoverlay=dwc2 # Add this below previous dtoverlay for gpio pins, enables new usb stack

Sound (Alsamixer) config #

You may have to add the user you’re using for this setup to the audio and dialout groups in order to work with audio and serial devices, so YMMV here:

usermod -a -G audio <USERNAME>
usermod -a -G dialout <USERNAME>



then press F6 to show all devices. Select the DigiRig sound device. Press F5 to show all options, then set the sound to 10, unmute the Mic and set to 10 as well, then set the Capture to 10. Disable the Automatic Gain by pressing m when highlighted. Esc to exit, then store the settings with

alsactl store

The above settings are only important when using an un-attenuated homebrew cable.

RaspAP config #

Install and configu raspAP

sudo raspi-config # Set Localisation for WiFi country

curl -sL | bash

During the install of RaspAP, respond Y to everything except VPN-related questions.

Once RaspAP installed, Login to the UI with admin/secret, then change:

  • Toggle Dark mode in the top bar
  • System > Advanced tab > Web server port to 8080, Save, go back to tab and restart lighttp
  • Authentication > Update password
  • Hotspot > Basic tab > SSID, change to preferred name
  • Hotspot > Basic tab > Wireless Mode, change to “802.11n”
  • Hotspot > Security tab > Change PSK to preferred value
  • Hotspot > Advanced tab > Toggle “Hide SSID in broadcast” to on
  • Hotspot > Advanced tab > Change Maximum number of clients to 5

Dire Wolf config #

Empty the /home/aprs/direwolf.conf file and replace it with the contents below. Remember to replace the callsign with your own!

ADEVICE  plughw:1,0
MODEM 1200
PTT /dev/ttyDigiRig RTS

DIGIPEAT 0 0 ^WIDE[3-7]-[1-7]$|^TEST$ ^WIDE[12]-[12]$ TRACE

# Enable GPS beaconing
SMARTBEACONING  60 2:00  5 15:00  0:15 30 255

To auto-run Dire Wolf on boot, add this to crontab -e:

* * * * *  $HOME/  >/dev/null  2>&1

Ublox GPS caveat #

If using a UBlox-based GPS puck, modify the script and append the following before Dire Wolf is started. It will reset the GPS device state prior to starting Dire Wolf.

ubxtool -p RESET

This “fix” is because of an issue with the UBlox-based GPS puck I used not updating past the first location lock. This issue took me days to diagnose and pin down a bandaid fix for. It is optional to include it in the command above here so if you’re not using a UBlox-based GPS device your mileage may vary.

Hardening #

Disable bluetooth #

Let’s disable the Bluetooth modem as it’s not needed for our purposes (unless you plan to use it). Add the following to the /boot/config.txt:

# Disable Bluetooth

then disable any bluetooth-related services and uninstall packages with:

sudo systemctl disable hciuart.service
sudo systemctl disable bluealsa.service
sudo systemctl disable bluetooth.service
sudo apt-get purge bluez -y
sudo apt-get autoremove -y

Firewall #

Setup a simple firewall to keep people from abusing connecting to the rPi wireless network. There is a lot more that could be done here but this is not a linux server ssh hardening article.

sudo apt-get install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit 2022/tcp comment 'SSH port rate limit'
sudo ufw limit 8001/tcp comment 'KISS port for Dire Wolf'
sudo ufw logging on
sudo ufw enable

Don’t forget to disable IPV6 in UFW; change IPV6=yes to IPV6=no:

sudo vim /etc/default/ufw
sudo ufw disable && sudo ufw enable

Disable the swapfile #

We want to write as little to the SD card as possible to extend the life of it, and 4GB of memory is more than enough to run things without swapping.

sudo systemctl stop dphys-swapfile
sudo systemctl disable dphys-swapfile
sudo apt-get purge dphys-swapfile

Watchdog #

It’s advisable to protect against random lockups and issues using the hardware “watchdog” built into the Raspberry Pi. This is a piece of hardware built into the SoC that continually counts down a counter — if it ever reaches zero, a hard reset of the system is generated.

There is a watchdog daemon that “feeds” the watchdog by reseting the counter periodically. Run the following enable the daemon:

sudo apt-get install watchdog

Modify /etc/watchdog to set the device line as follows:

watchdog-device = /dev/watchdog

Edit the /etc/systemd/system/watchdog.service file to include autostart by copying as follows:

sudo cp /lib/systemd/system/watchdog.service /etc/systemd/system/watchdog.service

Edit the previous file to add this line:


Edit /etc/sysctl.conf to add the line:


which forces a reboot 10 seconds after a kernel panic.

Resources #

Here’s a list of some of the resources I used to compile this information: