Build SvxLink from source (Debian / Ubuntu / Raspberry Pi)
- What this covers
- Compiling stock SvxLink (svxlink node, svxreflector, RemoteTrx) on Debian 12/13 (bookworm/trixie) or Ubuntu 22.04/24.04 — PC or Raspberry Pi (64-bit). The same procedure works for forks: just clone a different repository.
#!/bin/bash
set -e
# --- Build dependencies ------------------------------------------------
# Package names drift between releases. If apt says
# "Unable to locate package X": apt search <part-of-name>
# (e.g. apt search libgpiod) and pick the closest -dev package.
sudo apt update
sudo apt install -y \
build-essential cmake git wget curl sox alsa-utils vorbis-tools \
libgpiod-dev `# pulls the right runtime: libgpiod2 (bookworm/ubuntu) or libgpiod3 (trixie)` \
libsigc++-2.0-dev libgsm1-dev libpopt-dev \
tcl8.6-dev `# NOT tcl9.0-dev - svxlink wants 8.6 (apt list -a 'tcl*-dev' shows yours)` \
libgcrypt20-dev libssl-dev libspeex-dev libasound2-dev libopus-dev \
librtlsdr-dev libjsoncpp-dev libcurl4-gnutls-dev libogg-dev
# Optional, only for the Qtel EchoLink GUI (skip on headless/RPi):
# sudo apt install -y qtbase5-dev qttools5-dev qttools5-dev-tools
# Optional, only for "make doc": doxygen groff
# --- svxlink system user -----------------------------------------------
id -u svxlink >/dev/null 2>&1 || sudo useradd -r -G audio,plugdev,dialout svxlink
getent group gpio >/dev/null && sudo usermod -aG gpio svxlink # RPi: GPIO PTT
# --- Fetch and build ---------------------------------------------------
mkdir -p ~/projects && cd ~/projects
[ -d svxlink ] || git clone https://github.com/sm0svx/svxlink.git
mkdir -p svxlink/src/build && cd svxlink/src/build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DSYSCONF_INSTALL_DIR=/etc \
-DLOCAL_STATE_DIR=/var -DWITH_SYSTEMD=yes ..
make -j"$(nproc)"
sudo make install
sudo ldconfig
# --- Sound files (English + Swedish) -----------------------------------
cd ~/projects
[ -d svxlink-sounds-en_US-heather ] || git clone https://github.com/sm0svx/svxlink-sounds-en_US-heather.git
[ -d svxlink-sounds-sv_SE-elin ] || git clone https://github.com/sm0svx/svxlink-sounds-sv_SE-elin.git
cp svxlink/src/svxlink/scripts/filter_sounds.sh .
sudo ./filter_sounds.sh svxlink-sounds-en_US-heather en_US
sudo ./filter_sounds.sh svxlink-sounds-sv_SE-elin sv_SE
sudo tar xjf svxlink-sounds-en_US.tar.bz2 -C /usr/share/svxlink/sounds
sudo tar xjf svxlink-sounds-sv_SE.tar.bz2 -C /usr/share/svxlink/sounds
# --- Enable what this machine should run -------------------------------
# Node: sudo systemctl enable --now svxlink
# Reflector: sudo systemctl enable --now svxreflector
- "Unable to locate package …"
- Find the real name on your release: apt search libgpiod, apt list -a 'tcl*-dev' or apt-cache policy <package>. Rule of thumb: install the -dev package — its name is stable across releases, while runtime libraries carry version suffixes that differ (libgpiod2 vs libgpiod3).
- "fatal error: some/header.h: No such file"
- Find which package ships the header: sudo apt install apt-file && sudo apt-file update, then apt-file search header.h — install the -dev package it points to and re-run cmake.
- Raspberry Pi notes
- 64-bit Raspberry Pi OS builds fine with the same script. The gpio group above is what allows GPIO PTT. On a Pi 3, use make -j2 to avoid running out of RAM.
Configure the node — radio side (svxlink.conf)
- Skeleton
- A minimal simplex node: one logic, one receiver, one transmitter. Everything lives in /etc/svxlink/svxlink.conf:
[GLOBAL]
LOGICS=SimplexLogic,ReflectorLogic
CFG_DIR=svxlink.d
CARD_SAMPLE_RATE=48000
[SimplexLogic]
TYPE=Simplex
RX=Rx1
TX=Tx1
CALLSIGN=SM0ABC
MODULES=ModuleHelp,ModuleParrot
REPORT_CTCSS=136.5 ; subtone your node transmits
DEFAULT_LANG=en_US
[Rx1]
TYPE=Local
AUDIO_DEV=alsa:plughw:0
AUDIO_CHANNEL=0
SQL_DET=CTCSS ; VOX works too, CTCSS is cleaner
CTCSS_FQ=136.5
SQL_HANGTIME=2000
[Tx1]
TYPE=Local
AUDIO_DEV=alsa:plughw:0
AUDIO_CHANNEL=0
PTT_TYPE=SerialPin ; on a Raspberry Pi instead:
PTT_PORT=/dev/ttyUSB0 ; PTT_TYPE=GPIOD
PTT_PIN=DTRRTS ; PTT_GPIOD_CHIP=gpiochip0 PTT_GPIOD_LINE=17
- CTCSS → talkgroup
- With CTCSS_TO_TG= in the logic section, different subtones select different talkgroups — that is what populates the tone table in this portal.
Set up a SvxLink node (connect to this network)
- 1. Register
- Create an account on this portal first (see Getting Started) so the administrator knows who the node belongs to.
- 2. Configure ReflectorLogic
- In /etc/svxlink/svxlink.conf on your node:
[ReflectorLogic]
TYPE=Reflector
HOSTS=svx.sa7aux.se
CALLSIGN="SM0ABC-1" ; your node callsign (with -suffix if you run several)
CERT_EMAIL=you@example.com ; used in your node certificate
CERT_DOWNLOAD_CA_BUNDLE=1
CERT_CAFILE=/var/lib/svxlink/pki/ca-bundle.pem
DEFAULT_TG=240
MONITOR_TGS=240,2400
EVENT_HANDLER=/usr/share/svxlink/events.tcl
NODE_INFO_FILE=/etc/svxlink/node_info.json
- 3. First connect — certificate
- Add the logic to LOGICS= in [GLOBAL] and start svxlink. On first connect the node automatically sends a Certificate Signing Request. When the administrator signs it, the certificate is delivered to your node automatically and it comes online — nothing more to do on your side.
- Fill in node_info.json
- QTH, locator, frequencies and CTCSS in /etc/svxlink/node_info.json is what makes your node show up properly in the portal (map, frequencies, tone table).
Build the USRP fork (svxlink-usrp)
- What it is
- DL1HRC's SvxLink fork with UsrpLogic — bridges USRP audio (AllStar chan_usrp, DVSwitch Analog_Bridge) into SvxLink. UsrpLogic lives in contrib and is built automatically.
# Same build dependencies as the stock guide above, then:
cd ~/projects
git clone https://github.com/dl1hrc/svxlink.git svxlink-usrp
cd svxlink-usrp
git checkout svxlink-usrp
mkdir -p src/build && cd src/build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DSYSCONF_INSTALL_DIR=/etc \
-DLOCAL_STATE_DIR=/var -DWITH_SYSTEMD=yes ..
make -j"$(nproc)"
sudo make install && sudo ldconfig
- Configuration
- Add a [UsrpLogic] section to svxlink.conf — see the UsrpLogic.conf man page shipped with the fork for the USRP host/port settings.
Configure UsrpLogic (svxlink.conf)
[UsrpLogic]
TYPE=Usrp
USRP_HOST=127.0.0.1
USRP_TX_PORT=4002 ; svxlink sends here (Asterisk listens)
USRP_RX_PORT=4001 ; svxlink listens here (Asterisk sends)
CALL=N0CALL
DV_USER_INFOFILE=/etc/svxlink/dv_users.json
JITTER_BUFFER_DELAY=100
SHARE_USERINFO=1
- Wiring it up
- Add UsrpLogic to LOGICS= and connect it to your ReflectorLogic with a LinkManager section (see the svxlink.conf man page) — the reflector TG the bridge lands on is the logic's DEFAULT_TG. The other end of the UDP port pair is the AllStar side — see the AllStar tab.
Build GeuReflector (trunked reflector)
- What it is
- A fork of SvxReflector (trunk extension by IW1GEU) that links multiple reflectors into a federated mesh — talkgroups are routed to their owning server by numeric prefix. This network runs SA2BLV's fork of it.
# Same build dependencies as the stock guide above, plus:
sudo apt install -y libhiredis-dev `# or build with -DWITH_REDIS=OFF`
cd ~/projects
git clone https://github.com/sa2blv/GeuReflector.git
cd GeuReflector
git checkout SwedenReflectors
mkdir -p src/build && cd src/build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DSYSCONF_INSTALL_DIR=/etc \
-DLOCAL_STATE_DIR=/var -DWITH_SYSTEMD=yes ..
make -j"$(nproc)"
sudo make install && sudo ldconfig
sudo systemctl enable --now svxreflector
Configure trunks (svxreflector.conf)
- How routing works
- Each reflector owns all talkgroups whose number starts with its prefix (like telephone country codes). Trunk peers exchange audio over UDP and talkgroups are routed to the owning server automatically.
[GLOBAL]
LOCAL_PREFIX=240 ; this reflector owns TG 240*, 2400*, ...
[ReflectorTrunk]
GatewayId=SE-MYREFLECTOR ; this server's identity on the trunk network
Port=5500 ; UDP trunk port
Peers=SE-AUX ; comma-separated [TrunkPeer#...] names
[TrunkPeer#SE-AUX]
Host=reflector.example.com
Port=5500
TGRule=^.*$ ; regex: which TGs may cross this trunk
Retransmit=0
ActiveFilter=0
Key=CHANGEME ; shared secret, same on both sides
- Joining an existing network
- Both sides must agree on peer name, port and key. To peer with this network, contact the administrator.
Run your own reflector: basics & password login
- Basics
- In /etc/svxlink/svxreflector.conf: LISTEN_PORT=5300 is what nodes connect to, HTTP_SRV_PORT=8090 serves the /status JSON that dashboards read.
- Password login (legacy v1/v2 clients)
- [USERS] maps a callsign to a key group and [PASSWORDS] holds each group's secret — several nodes can share one group:
[USERS]
SM0ABC-1=MyNodes
SM0ABC-2=MyNodes
SM3XYZ=SM3XYZ
[PASSWORDS]
MyNodes="a strong shared key"
SM3XYZ="another strong password"
Certificates (PKI)
- The reflector is its own CA
- On first start the reflector creates a complete PKI from the [ROOT_CA], [ISSUING_CA] and [SERVER_CERT] sections — fill in your own organisation and set COMMON_NAME/SUBJECT_ALT_NAME in [SERVER_CERT] to your reflector's public hostname:
[GLOBAL]
CERT_PKI_DIR=/etc/svxlink/pki
CERT_CA_BUNDLE=/etc/svxlink/pki/ca-bundle.crt
CERT_CA_KEYS_DIR=/etc/svxlink/pki/private/
CERT_CA_PENDING_CSRS_DIR=/etc/svxlink/pki/pending_csrs/
CERT_CA_CSRS_DIR=/etc/svxlink/pki/csrs/
CERT_CA_CERTS_DIR=/etc/svxlink/pki/certs/
#ACCEPT_CALLSIGN="[A-Z0-9][A-Z]{0,2}\d[A-Z0-9]{0,3}[A-Z](?:-[A-Z0-9]{1,3})?"
[SERVER_CERT]
COMMON_NAME=reflector.example.com
SUBJECT_ALT_NAME=DNS:reflector.example.com
ORG=MYCLUB
COUNTRY=SE
EMAIL_ADDRESS=you@example.com
- Signing node certificates
- Incoming node CSRs land in CERT_CA_PENDING_CSRS_DIR until an administrator signs them; the signed certificate is then pushed to the node automatically over the reflector connection. Use the ACCEPT_CALLSIGN= regex to restrict who may even submit one.