AX.25 HOWTO: packet radio and APRS on Linux with Dire Wolf

Updated November 2026

AX.25 is the link-layer protocol of amateur packet radio, and APRS (the position and messaging network) is built on it. On Linux in 2026 the usual set-up is a radio, a cheap USB sound interface and the Dire Wolf software TNC. The big change this year: the kernel's own AX.25 stack was removed from mainline Linux in version 7.1, so how you connect applications now depends on your kernel.

The classic AX25-HOWTO (2001), which covers NET/ROM, ROSE and the node software in depth, is kept by the Linux Documentation Project at tldp.org.

You need an amateur radio licence to transmit. Receiving and decoding is open to anyone, but every transmission, including automatic beacons and digipeating, must come from a licensed station using its own callsign. In the United States, Part 97 of the FCC rules applies: for example, you must identify at least every 10 minutes and at the end of a contact (47 CFR 97.119), and you may not send messages encoded to hide their meaning (47 CFR 97.113), so no encryption on the air. Other countries have similar rules; check your national regulator.

How the pieces fit

A TNC (terminal node controller) turns AX.25 frames into audio tones and back. Hardware TNCs still exist, but a sound card plus Dire Wolf does the same job in software. Applications talk to the TNC in one of three ways:

The kernel AX.25 situation

In April 2026 the network maintainers removed the AX.25, NET/ROM and ROSE protocols and all hamradio drivers (mkiss, 6pack, bpqether, baycom, yam, scc) from the kernel tree. The commit says the code had long attracted a flood of bug reports and nobody had stepped up to help handle them; it moves the code to an out-of-tree repository, linux-netdev/mod-orphan, from which it can return if it is cleaned up. Linux 7.0 is the last release that contains it.

Kernel AX.25 by kernel version, as of November 2026
KernelKernel AX.25Examples
7.0 and olderIn the source tree (whether your distribution builds it is up to the distribution)Debian 13 (6.12, which builds ax25 and mkiss as modules), Ubuntu 24.04 (6.8), Ubuntu 26.04 LTS (7.0), the 6.12 and 6.18 long-term kernels
7.1 and newerGone; only with the out-of-tree modulesFedora 43, 44 and 45 and Arch Linux (all on 7.2 kernels), the Debian 13 backports kernel (7.2), and every newer mainline or stable kernel

Check your own system:

uname -r
modinfo ax25 mkiss 2>&1 | grep -E '^(filename|modinfo)'

If modinfo finds both modules, the kernel route works. If not, either use applications that speak KISS or AGW over TCP directly (no kernel support needed), or build the out-of-tree modules. Their README says to build on the machine that will load them: make, sudo make install, sudo depmod -a. They must be rebuilt for every kernel update, and with Secure Boot they must be signed (see the Kernel HOWTO).

Set up Dire Wolf

Dire Wolf decodes and sends 300 baud AFSK (HF), 1200 baud AFSK (the usual VHF/UHF packet and APRS speed), 2400/4800 PSK and 9600 baud G3RUH, adds FX.25 forward error correction, and can act as an APRS digipeater and Internet gateway (IGate). As of November 2026 the current release is 1.8.1 (November 2025); Debian 13 packages 1.7, and 1.8.1 is in trixie-backports. The project notes that distribution packages lag behind.

sudo apt install direwolf          # Debian, Ubuntu
arecord -l                         # find the card number of your USB sound interface
aplay -l

Dire Wolf reads direwolf.conf from the current directory, then from your home directory, or from the file given with -c. A minimal configuration for one 1200 baud channel on USB sound card 1, keying the radio through the CM108 chip's GPIO (common on radio interface boards):

# ~/direwolf.conf
ADEVICE plughw:1,0
CHANNEL 0
MYCALL N0CALL-10
MODEM 1200
PTT CM108
AGWPORT 8000
KISSPORT 8001

Replace N0CALL-10 with your own callsign and an SSID (1 to 15). Other PTT choices are a serial control line (PTT /dev/ttyUSB0 RTS) and a GPIO line (PTT GPIOD 0 25, chip and line number). Start it in a terminal so you can watch the decoded traffic:

direwolf -c ~/direwolf.conf

It reports the audio device in use, then "Ready to accept AGW client application 0 on port 8000" and the same for KISS on port 8001. Tune the radio to a busy packet or APRS frequency and decoded frames should scroll past. If you see nothing, the audio level is the usual cause: Dire Wolf prints the received level, and its User Guide and Radio Interface Guide explain how to set it.

Network ports. Dire Wolf's guide suggests disabling the AGW or KISS port (set it to 0) on systems exposed to the Internet. Otherwise firewall ports 8000 and 8001 so that only your own machines can reach them, since anything connecting there can transmit under your callsign.

APRS without any kernel support

For APRS you do not need kernel AX.25 at all. Dire Wolf can beacon your position (PBEACON), digipeat (DIGIPEAT 0 0 ^WIDE1-1$ ^WIDE1-1$ for a simple fill-in digipeater) and gate traffic to the APRS-IS Internet network (IGSERVER and IGLOGIN), all from its configuration file. Mapping programs such as Xastir connect to its AGW or KISS TCP port. Read the APRS sections of the User Guide before you enable digipeating; badly chosen paths flood the channel for everyone.

Connect Dire Wolf to kernel AX.25

On a kernel that still has AX.25 (7.0 or older, or with the out-of-tree modules), install the tools and describe the port in /etc/ax25/axports:

sudo apt install ax25-tools ax25-apps
# /etc/ax25/axports
# name  callsign    speed  paclen  window  description
radio   N0CALL-10   1200   255     2       Dire Wolf 1200 baud

Remove blank lines from axports; the Dire Wolf guide warns that they cause trouble. Start Dire Wolf with -p, which creates a KISS pseudo-terminal and the link /tmp/kisstnc, then attach it. kissattach wants the real device, not the symbolic link:

direwolf -p -c ~/direwolf.conf &
sudo kissattach "$(readlink -f /tmp/kisstnc)" radio
ip link show ax0

Now the AX.25 programs work with the port name from axports:

sudo axlisten -a -c                 # monitor all frames, in color
axcall radio N0CALL-1               # connect to a station or BBS; ~. to disconnect
sudo beacon -s radio "Test from N0CALL-10"   # send one beacon frame

The Dire Wolf guide notes that the pseudo-terminal can stall if nothing reads from it, and prefers the network ports where an application supports them. Also, if you give the ax0 interface an IP address, programs that broadcast on every interface (Samba, Avahi and others) will start transmitting over the radio. Bind those services to specific interfaces or filter ax0 with your firewall.

Common mistakes

Sources