Dire Wolf service management
Use systemd to start and supervise Dire Wolf
This page shows two practical systemd unit examples for running Dire Wolf on Linux. They are usually easier to support over time than relying on screen or tmux because the service state, logs, and restart behavior are visible through standard tools. I highly recommend not trying to use screen or tmux, even when starting direwolf through systemd. Using screen or tmux adds complexity and makes it harder to see the service state and logs.
Start with the single-instance unit if you have one Dire Wolf configuration. Move to the template unit when you want separate services for different radios or config files.
The examples below run the Dire Wolf binary directly, which keeps the service simple to debug. In this case, you are troubleshooting the direwolf process itself rather than a shell wrapper script and screen session and direwolf.
Referenced gists
1) Single-instance service: direwolf.service gist
2) Multi-instance template service: direwolf@.service gist
Advantages to using systemd to manage Dire Wolf
The Linux systemd model is the standard way to start and supervise long-running processes. It has been optimized over many years to handle service dependencies, logging, and process supervision. The biggest day-2 operations win with systemd is that service behavior, health, and logs are all visible through standard tools. This reduces hand-maintained scripts and the amount of "tribal knowledge" needed to support a station over time.
| Topic | systemd service |
|---|---|
| Automatic restart | Built in (Restart=always, RestartSec=15) options.
Easily adjustable. |
| Boot ordering |
Explicit dependencies (After=network.target,
After=rigctld.service). Ensures Dire Wolf starts after required
services are ready, such as sound and network.
|
| Logging | journalctl -u ..., built-in history and follow mode. Logs are centralized
and automatically rotated. |
| Operational control | start, stop, status, enable,
disable |
| Least privilege | Run as non-root user via User= and Group=. Minimizes
security risks of running services as root. |
| Multi-instance support | Native with template units like direwolf@.service |
| Operator handoff | Any operator can run the same standard commands to see status, logs, and restart history. |
For more information on systemd, see systemd site.
Recommended starting point
Choose the single-instance unit for a one-radio setup. Use the template unit when you need
multiple named services with different config files. Before copying either example, replace
YOUR_USERNAME, YOUR_GROUP, and the paths under
/opt/direwolf with values that match your system.
The -a option determines how often direwolf prints audio level statistics (in seconds).
This can be adjusted if you are debugging decoding issues.
These examples assume your Dire Wolf config file(s) are stored in
/opt/direwolf/, so move your existing direwolf.conf (and any
direwolf-*.conf files) there before enabling the service.
Note: make sure that the specified user has permissions to access the Dire Wolf config.
Option A: Single-instance service
Use this when you have one Dire Wolf config and one running process.
[Unit]
Description=Dire Wolf Sound Card-based AX.25 TNC
After=network.target
After=sound.target
[Service]
Type=simple
User=YOUR_USERNAME
Group=YOUR_GROUP
WorkingDirectory=/opt/direwolf/
ExecStart=/usr/local/bin/direwolf -t 1 -a 600 -c direwolf.conf
Restart=always
RestartSec=15
[Install]
WantedBy=multi-user.target
Example: starting direwolf uses
/opt/direwolf/direwolf.conf.
Option B: Multi-instance template service
Use this when you want multiple named Dire Wolf instances with different config files.
[Unit]
Description=Dire Wolf %i Service
Documentation=https://github.com/wb2osz/direwolf/blob/dev/doc/README.md
After=network-online.target
After=sound.target
Wants=rigctld.service
After=rigctld.service
[Service]
Type=simple
User=YOUR_USERNAME
Group=YOUR_GROUP
WorkingDirectory=/opt/direwolf/
ExecStart=/usr/local/bin/direwolf -a 200 -qd -c direwolf-%i.conf
Restart=always
RestartSec=15
[Install]
WantedBy=multi-user.target
Example: starting direwolf@vhf uses
/opt/direwolf/direwolf-vhf.conf.
For a second instance, direwolf@hf uses
/opt/direwolf/direwolf-hf.conf.
Using Wants=rigctld.service makes rigctld optional
and starts it if available. Dire Wolf will still start if rigctld
is not installed.
For more details on Dire Wolf configuration and command-line arguments, see the Dire Wolf User Guide.
Install and enable
For single instance
sudo cp direwolf.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now direwolf
sudo systemctl status direwolf
For template instances
sudo cp "direwolf@.service" /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now direwolf@vhf
sudo systemctl status direwolf@vhf
Logs and troubleshooting
# Single instance logs
journalctl -u direwolf -f
# Template instance logs
journalctl -u direwolf@vhf -f
Keep After=rigctld.service when PTT depends on rigctld. Use
Requires=rigctld.service only if you want Dire Wolf startup to fail when
rigctld is unavailable.
Seeing terminal-style text with journalctl
If you like the colored terminal view from screen, you can keep most of that experience with systemd and journalctl.
# 1) Keep -t 1 in ExecStart so Dire Wolf emits ANSI color
ExecStart=/usr/local/bin/direwolf -t 1 -a 600 -c direwolf.conf
# 2) Follow logs in a cleaner, terminal-like format
journalctl -u direwolf -f -o cat --all
# 3) For template instances
journalctl -u direwolf@vhf -f -o cat --all
If colors do not appear, try --no-pager and confirm your terminal emulator
supports ANSI colors.
Systemd debugging
A key supportability advantage: if Dire Wolf exits, the screen session may disappear with the error text that was on screen. With systemd, stdout/stderr is captured in journald and remains available after the process exits.
| Debug task | systemd workflow |
|---|---|
| Did startup fail? |
systemctl status direwolf immediately shows exit code, last logs, and
unit state.
|
| Find recent errors |
journalctl -u direwolf --since "15 minutes ago" gives a time-bounded log view.
|
| Follow live behavior | journalctl -u direwolf -f is the standard live tail. |
| Post-crash evidence retention |
journalctl -u direwolf --since "1 hour ago" preserves crash messages even
after service exit/restart.
|
| Root-cause restart loops |
Restart policy and cadence are explicit in one place
(Restart=always, RestartSec=15) and easily adjusted.
|
| See which command actually started |
systemctl show direwolf -p ExecStart,FragmentPath shows exact unit
command and source file.
|
| Dependency visibility |
Unit declares ordering/dependencies with
After=/Wants=/Requires=.
|
# Fast systemd debug checklist
systemctl status direwolf@vhf
journalctl -u direwolf@vhf --since "-30 min"
journalctl -u direwolf@vhf -f
systemctl show direwolf@vhf -p ActiveState,SubState,ExecMainStatus,FragmentPath
Migrating from cron and dw-start.sh
Before trying to start Dire Wolf with systemd, make sure any old crontab entries that
launch Dire Wolf through dw-start.sh are removed or commented out. Running
both methods together can create duplicate processes and audio/PTT conflicts.