#!/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
[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
[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
# 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
[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
# Same build dependencies as the SvxLink tab, then:
cd ~/projects
git clone https://git.sa7aux.se/bjorne/svxlink-fork-usrp.git svxlink-usrp
cd svxlink-usrp
git checkout opus-fec-260723 # tagged patched version
# or: git checkout opus-inband-fec # the branch it lives on
mkdir -p src/build && cd src/build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DSYSCONF_INSTALL_DIR=/etc \
-DLOCAL_STATE_DIR=/var -DWITH_SYSTEMD=yes -DUSE_QT=OFF ..
make -j"$(nproc)"
sudo make install && sudo ldconfig
[ReflectorLogic] ; ... existing settings ... OPUS_ENC_INBAND_FEC=1 ; enable Opus in-band forward error correction OPUS_ENC_PACKET_LOSS=10 ; expected packet loss %, drives FEC redundancy
# 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
[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
[USERS] SM0ABC-1=MyNodes SM0ABC-2=MyNodes SM3XYZ=SM3XYZ [PASSWORDS] MyNodes="a strong shared key" SM3XYZ="another strong password"
[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
. /etc/os-release; echo $VERSION_CODENAME # trixie / bookworm dpkg --print-architecture # amd64 / arm64
sudo apt install ./asl3-chan-svx_0.2.4~<os>_<arch>.deb
load = chan_svx.so
rxchannel = SVX/<section>
sudo asterisk -rx "core restart now" sudo asterisk -rx "svx show"
. /etc/os-release; echo $VERSION_CODENAME # bookworm (12) / trixie (13) sudo apt install ./chan-pbx-sat_<ver>~<suite>_amd64.deb # on a FreePBX box, add the GUI: sudo apt install ./pbxsat-freepbx_<ver>~<suite>_all.deb
sudo dnf install ./chan-pbx-sat-<ver>.<asttag>.<dist>.x86_64.rpm # on a FreePBX box, add the GUI: sudo dnf install ./pbxsat-freepbx-<ver>.<asttag>.<dist>.noarch.rpm
The module only writes pbx_sat.conf. A working bridge also needs a few standard FreePBX pieces (an extension, the module loaded, a dial-plan entry). This is the whole chain, in order. Replace mytrunk, 91 and the talkgroup / extension numbers with your own.
# /etc/asterisk/modules.conf (under [modules]) load = chan_pbx_sat.so sudo fwconsole restart # or: asterisk -rx "module load chan_pbx_sat.so" asterisk -rx "pbxsat status" # should print JSON, not an error
; dial 91<tg> to key up talkgroup <tg> on "mytrunk"
; (91 = this trunk's Group number; mytrunk = its name)
[pbxsat-mytrunk](+)
exten => _91.,1,Answer()
same => n,Dial(PBXSAT/mytrunk/${EXTEN:2}) ; :2 strips the "91" prefix
same => n,Hangup()
Each trunk carries a full audio chain per direction (rx = reflector→phone, tx = phone→reflector): preamp gain → 7-band EQ → AGC → limiter. It is off by default — a trunk that sets nothing passes audio through bit-for-bit, so this can never colour a link you didn't ask it to. The most useful piece on a phone path is the limiter (stops a hot caller clipping into the reflector) and AGC (evens out wildly different phone levels); the EQ is there for a low-cut / presence lift if you want it.