This tool allows Zello Free or Zello Work channels to be connected to USRP, enabling bridging of amateur radio networks to the Zello network.
Tested with:
- AllStarLink
chan_usrp
- DVSwitch
Analog_Bridge
- MMDVM_CM
USRP2DMR
andUSRP2YSF
- SvxLink via a third-party USRP module
The original inspiration for this project was the work done by Rob G4ZWH to build a public Zello bridge to the FreeSTAR network using SIP softphones and the Zello Windows client. This was well received but had limitations. Matt G4IYT later rebuilt the bridge as a dedicated service using the Zello Channels API.
Current users of the bridge include:
The bridge does not require significant resources. The FreeSTAR bridge runs on a VPS with 1 VCPU and 1GB RAM, and performs well on both AMD64 and ARM platforms.
The bridge needs a Zello account to log into. This account represents the “user” speaking whenever traffic is sent from AllStarLink into Zello.
Recommended setup:
- Create a dedicated Zello account for the bridge (do not use your personal account).
- Ensure this account has permission to talk and listen in your Zello channel.
- Convert this account into a developer account by logging into the Zello Developers Console.
- Under Keys, click Add Key. Save both the Issuer and the Private Key.
The private key is long. Copy the entire contents and save them to a
.key
file (for example,/opt/asl-zello-bridge/zello.key
). You will reference this file in your service configuration.
These instructions were tested with Debian 12. Adjust as needed for other systems.
There are three installation methods:
- pip + venv (recommended): modern, isolated, avoids interfering with system packages.
- setup.py (deprecated): used in early versions, but may break system dependencies.
- docker: containerized deployment on Docker/Podman/Kubernetes.
The
setup.py
method is deprecated in favor ofpip + venv
. Users have reported issues on Debian 12 and Ubuntu 24. If you installed withsetup.py
, it will still work, but upgrading is recommended.
apt-get install libogg-dev libopusenc-dev libflac-dev libopusfile-dev libopus-dev libvorbis-dev libopus0 git
Install Python dependencies:
apt-get install python3-venv python3-pip
Download code:
cd /opt
git clone https://github.com/mattmelling/asl-zello-bridge.git
Create venv:
mkdir -p /opt/asl-zello-bridge/venv
python3 -m venv /opt/asl-zello-bridge/venv
Install pyogg
from source:
git clone https://github.com/TeamPyOgg/PyOgg.git
cd PyOgg
/opt/asl-zello-bridge/venv/bin/python setup.py install
Install the bridge:
cd /opt/asl-zello-bridge
/opt/asl-zello-bridge/venv/bin/pip3 install .
Install pyogg
:
git clone https://github.com/TeamPyOgg/PyOgg.git
cd PyOgg
sudo python setup.py install
Install the bridge:
git clone https://github.com/mattmelling/asl-zello-bridge.git
cd asl-zello-bridge
sudo python3 setup.py install
At this point, asl_zello_bridge
should be on your $PATH
.
If you installed with setup.py
, adjust asl-zello-bridge.service
to point to where the script is installed:
sudo cp asl-zello-bridge.service /etc/systemd/system/
sudo systemctl edit asl-zello-bridge.service
When the editor opens, set environment variables under [Service]
.
[Service]
# IP where this program listens for USRP RX audio (usually localhost)
Environment=USRP_BIND=127.0.0.1
# IP where this program sends USRP TX audio (usually localhost)
Environment=USRP_HOST=127.0.0.1
# UDP port for audio received from USRP/AllStarLink
# 34001 is ASL default (rxchannel = USRP/127.0.0.1:34001:32001)
Environment=USRP_RXPORT=34001
# UDP port for audio sent back into USRP/AllStarLink
# 32001 is ASL default
Environment=USRP_TXPORT=32001
# Zello username (case-sensitive)
Environment=ZELLO_USERNAME=myuser
# Zello password
Environment=ZELLO_PASSWORD=mypass
# Zello channel name (must match exactly, case-sensitive)
Environment=ZELLO_CHANNEL="My Test Channel"
[Service]
# USRP parameters
Environment=USRP_BIND=127.0.0.1
Environment=USRP_HOST=127.0.0.1
Environment=USRP_RXPORT=34001
Environment=USRP_TXPORT=32001
# Zello credentials
Environment=ZELLO_USERNAME=myuser
Environment=ZELLO_PASSWORD=mypass
Environment=ZELLO_CHANNEL="My Test Channel"
# Zello Free variables
Environment=ZELLO_PRIVATE_KEY=/opt/asl-zello-bridge/zello.key
Environment=ZELLO_ISSUER=my-issuer-id
Environment=ZELLO_WS_ENDPOINT=wss://zello.io/ws
[Service]
# USRP parameters
Environment=USRP_BIND=127.0.0.1
Environment=USRP_HOST=127.0.0.1
Environment=USRP_RXPORT=34001
Environment=USRP_TXPORT=32001
# Zello credentials
Environment=ZELLO_USERNAME=myuser
Environment=ZELLO_PASSWORD=mypass
Environment=ZELLO_CHANNEL="My Test Channel"
# Zello Work variables
Environment=ZELLO_API_ENDPOINT=https://mynetwork.zellowork.com
Environment=ZELLO_WS_ENDPOINT=wss://zellowork.io/ws/mynetwork
# Log format (see Python logging docs)
Environment=LOG_FORMAT="%(levelname)s:%(name)s:%(message)s"
# RX audio gain in dB
Environment=USRP_GAIN_RX_DB=0
# TX audio gain in dB
Environment=USRP_GAIN_TX_DB=0
sudo systemctl enable asl-zello-bridge.service
sudo systemctl start asl-zello-bridge.service
Set up a node with a USRP channel in ASL (asl-menu
can add a new node number). Example rpt.conf
:
[1001](node-main)
rxchannel = USRP/127.0.0.1:34001:32001
duplex = 0 ; Half duplex, no telemetry or hang time
linktolink = yes ; Force full-duplex even with duplex=0
This creates node 1001
on your server connected to Zello. You can then link node 1001
to other nodes as desired.
To make node 1001
display nicely in Supermon/AllScan, add an entry to /etc/asterisk/privatenodes.txt
:
Node | Callsign | Description | Location
1001 | MyCall | Zello Channel | QTH
Append the entry:
echo "1001|MyCall|Zello Channel|QTH" | sudo tee -a /etc/asterisk/privatenodes.txt
Install support for privatenodes:
sudo apt install asl3-update-nodelist
privatenodes.txt
is not used by Allmon3. To override labels in Allmon3, add the line to the [node-overrides]
section of /etc/allmon3/web.ini
.
Append if the section already exists:
sudo sed -i '/^\[node-overrides\]/a 1001 = MyCall Zello Channel QTH' /etc/allmon3/web.ini
Restart Allmon3:
sudo systemctl restart allmon3
If [node-overrides]
does not exist, create it and add the line:
sudo sh -c 'grep -q "^\[node-overrides\]" /etc/allmon3/web.ini || echo "[node-overrides]" >> /etc/allmon3/web.ini'
echo "1001 = MyCall Zello Channel QTH" | sudo tee -a /etc/allmon3/web.ini
sudo systemctl restart allmon3
Resulting section:
[node-overrides]
1001 = MyCall Zello Channel QTH
A Dockerfile
is included:
docker build -t asl-zello-bridge .
Run with required environment variables (Zello Free example):
docker run --rm -it \
-e USRP_BIND=0.0.0.0 \
-e USRP_HOST=allstar.node \
-e USRP_RXPORT=34001 \
-e USRP_TXPORT=32001 \
-e ZELLO_WS_ENDPOINT=wss://zello.io/ws \
-e ZELLO_CHANNEL="My Test Channel" \
-e ZELLO_PRIVATE_KEY=/test.key \
-e ZELLO_USERNAME=myuser \
-e ZELLO_PASSWORD=mypass \
-e ZELLO_ISSUER=my-issuer-id \
-v /src/asl-zello-bridge/test.key:/test.key \
asl-zello-bridge
This also works with docker-compose
, Kubernetes, or any container runtime.
asl-zello-bridge
is built and maintained by Matt G4IYT
Special thanks to:
- Rob G4ZWH for inspiration and FreeSTAR bridge hosting
- Shane M0VUB for support on behalf of FreeSTAR
- Lee M0LLC for early adoption and CumbriaCQ testing
- Piotr G0TWP for SvxLink testing and bug discovery