GNU Radio on Linux — Complete Setup, Flowgraph and Ham Radio Guide
GNU Radio is the most powerful open-source SDR signal processing framework available. This complete guide covers installation on Ubuntu and Debian, understanding GNU Radio Companion, building your first receiver flowgraph, common ham radio applications including AX.25 packet, FM reception, and satellite decoding, scripting with Python, and the key differences between GNU Radio and ready-made applications like GQRX and OpenWebRX.
- What is GNU Radio and who it is for
- Installation on Ubuntu and Debian
- GNU Radio Companion — the visual flowgraph editor
- Key concepts — sources, sinks, and signal processing blocks
- Building your first receiver flowgraph
- FM broadcast receiver walkthrough
- Ham radio applications
- AX.25 packet radio with GNU Radio
- Satellite signal decoding
- Python scripting with GNU Radio
- Out-of-tree modules — extending GNU Radio
- Performance optimization
- GNU Radio vs GQRX vs OpenWebRX
- Troubleshooting common problems
- Frequently asked questions
What is GNU Radio and who it is for
GNU Radio is a free and open-source software development toolkit that provides signal processing blocks for implementing software radios. Where GQRX is a ready-to-use receiver application and OpenWebRX is a ready-to-use server, GNU Radio is the underlying framework that both are built on. It gives you the tools to build any signal processing application you can imagine — receivers, transmitters, decoders, analyzers, and more.
The central concept in GNU Radio is the flowgraph — a visual representation of a signal processing pipeline where data flows from a source (SDR hardware, file, or generated signal) through a chain of processing blocks (filters, demodulators, decoders) to a sink (audio output, file, or display). You build these flowgraphs either visually in GNU Radio Companion or programmatically in Python.
GNU Radio is not a replacement for GQRX or OpenWebRX for everyday monitoring — it is overkill for simply listening to amateur radio. Its strength is implementing custom signal processing that no existing application provides: decoding a proprietary protocol, building a custom transceiver, implementing a new digital mode, or doing SDR research.
Who should learn GNU Radio
- Operators who want to implement custom decoders for digital modes not supported by existing software
- Experimenters building software-defined transceivers for satellite operation or microwave work
- Students and researchers working in signal processing and wireless communications
- Developers who want to understand how GQRX, OpenWebRX, and WSJT-X work under the hood
- Contesters and DXers interested in advanced SDR techniques like I/Q signal analysis
Installation on Ubuntu and Debian
Ubuntu 22.04 and 24.04
sudo apt update
sudo apt install gnuradio gnuradio-dev \
gr-osmosdr python3-gnuradio
This installs the GNU Radio runtime, development headers, the OsmoSDR source block (supports RTL-SDR, HackRF, Airspy, and more), and Python bindings. The installation is large — expect 500 MB to 1 GB of packages.
Install SDR hardware support
# RTL-SDR
sudo apt install rtl-sdr librtlsdr-dev
# HackRF
sudo apt install hackrf libhackrf-dev
# Airspy
sudo apt install airspy libairspy-dev
# Blacklist DVB-T driver for RTL-SDR
echo "blacklist dvb_usb_rtl28xxu" | \
sudo tee /etc/modprobe.d/blacklist-rtl.conf
Build GNU Radio from source (latest version)
The repository version may be one or two major releases behind. For the latest features build from source using PyBOMBS or cmake directly:
sudo apt install git cmake build-essential \
libboost-all-dev libcppunit-dev swig \
doxygen libfftw3-dev libgsl-dev \
libqt5opengl5-dev python3-click \
python3-click-plugins python3-mako \
python3-scipy python3-zmq
git clone https://github.com/gnuradio/gnuradio.git
cd gnuradio
git checkout v3.10.x # use latest stable tag
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
sudo make install
sudo ldconfig
Verify installation
# Check version
gnuradio-config-info --version
# Launch GNU Radio Companion
gnuradio-companion
GNU Radio Companion — the visual flowgraph editor
GNU Radio Companion (GRC) is the graphical editor for building flowgraphs. It provides a canvas where you drag and drop signal processing blocks and connect them with wires to create a signal processing pipeline.
Launching GRC
gnuradio-companion
The GRC interface
- Canvas (center) — where you place and connect blocks to build your flowgraph
- Block library (right) — searchable list of all available signal processing blocks organized by category
- Properties panel — double-click any block to configure its parameters
- Toolbar — run, stop, and generate buttons at the top
What GRC does when you click Run
When you run a flowgraph GRC generates Python code from your visual design and executes it. The generated .py file is saved alongside your .grc file. You can read and modify this Python file directly — everything GRC does visually is plain Python using the GNU Radio API.
Block categories relevant to ham radio
| Category | Contents | Ham radio use |
|---|---|---|
| Sources | SDR hardware, file, signal generators | RTL-SDR input, replay I/Q files |
| Sinks | Audio output, file, network, display | Speaker output, waterfall display, file recording |
| Filters | Low pass, band pass, notch, rational resampler | Channel selection, decimation, noise reduction |
| Modulators | FM, AM, NBFM, WBFM demodulators | Voice demodulation from SDR |
| Channel Models | Noise sources, channel simulators | Testing decoders without hardware |
| Instrumentation | Waterfall, FFT, constellation, scope | Signal visualization and analysis |
| Packet Comms | HDLC framer, AX.25, GMSK | Packet radio and satellite TNC |
| Math Operations | Multiply, add, AGC, squelch | Signal level control |
Key concepts — sources, sinks, and signal processing blocks
Sample rate and decimation
The sample rate flowing through your flowgraph is the most important parameter to understand. Every block in the chain must handle samples at compatible rates. The SDR hardware produces samples at the configured rate (e.g. 2,400,000 samples/second for RTL-SDR). Decimation reduces this rate — a decimation of 10 produces 240,000 samples/second. After decimation the signal occupies a narrower bandwidth appropriate for a single channel.
# RTL-SDR hardware rate
samp_rate = 2400000 # 2.4 Msps — wide enough to see many channels
# After low-pass filter and decimation by 10
audio_rate = 240000 # 240 ksps — appropriate for FM demodulation
# After FM demodulation and audio decimation
output_rate = 48000 # 48 ksps — standard audio sample rate
Complex (I/Q) vs real signals
SDR hardware outputs complex samples — pairs of I (in-phase) and Q (quadrature) values that together represent both amplitude and phase. GNU Radio blocks that work with SDR input use complex data types (complex float). After demodulation the signal becomes real (a single audio stream). Wires in GRC are colour-coded: blue for complex, orange for float.
Frequency translation
The SDR is tuned to a center frequency. Signals at other frequencies appear offset from center in the passband. A Frequency Xlating FIR Filter block simultaneously shifts a signal from its offset position to baseband (0 Hz) and applies a low-pass filter to select only that signal — this is the standard way to select a single channel from the wide SDR input.
Variables in GRC
Use Variable blocks to define values used across multiple blocks — sample rate, center frequency, gain. Changing a variable automatically updates all blocks that reference it. This is cleaner than setting the same value in multiple places.
Building your first receiver flowgraph
The simplest useful flowgraph receives wideband FM broadcast radio from an RTL-SDR. Here is the block chain and how to build it in GRC.
Blocks needed
- Options block — already present in every new flowgraph, set title and generate options
- Variable block — set
samp_rate = 2000000 - RTL-SDR Source — from Sources category, set sample rate to samp_rate variable
- WBFM Receive — from Modulators category, handles FM demodulation
- Rational Resampler — converts from FM output rate to audio rate
- Audio Sink — plays the demodulated audio through speakers
- QT GUI Frequency Sink — optional waterfall display
Step-by-step in GRC
- Open GRC and create a new flowgraph (File → New)
- Double-click the Options block and set Generate Options to QT GUI
- Add a Variable block, name it
samp_rate, value2000000 - Add a Variable block, name it
freq, value100000000(100 MHz — change to a local FM station) - Search for "RTL-SDR Source" in the block library and drag it to the canvas
- Double-click it and set Sample Rate to
samp_rate, Frequency tofreq - Add a WBFM Receive block, set Quadrature Rate to
500000 - Add a Rational Resampler, set Decimation to
10, Interpolation to1(converts 500000 → 48000 ksps) - Add an Audio Sink, set Sample Rate to
48000 - Connect blocks: RTL-SDR → WBFM Receive → Rational Resampler → Audio Sink
- Click Run — you should hear the FM broadcast station
Adding a waterfall display
Add a QT GUI Frequency Sink block and connect it to the output of the RTL-SDR Source (you can split one output to multiple blocks). Set the bandwidth to samp_rate. When you run the flowgraph a spectrum display window opens alongside the running receiver.
FM broadcast receiver walkthrough
Here is the complete Python script that GRC generates for a basic FM receiver — useful for understanding how flowgraphs translate to code and for running without GRC:
#!/usr/bin/env python3
from gnuradio import gr, audio, analog
from gnuradio import filter as grfilter
import osmosdr
class fm_receiver(gr.top_block):
def __init__(self):
gr.top_block.__init__(self, "FM Receiver")
samp_rate = 2000000
freq = 100.0e6 # Change to your local FM station
# RTL-SDR source
self.src = osmosdr.source(args="rtl=0")
self.src.set_sample_rate(samp_rate)
self.src.set_center_freq(freq)
self.src.set_gain(40)
# WBFM demodulator
self.wbfm = analog.wfm_rcv(
quad_rate=500000,
audio_decimation=10
)
# Low-pass filter and decimation to audio rate
self.lpf = grfilter.rational_resampler_fff(
interpolation=48,
decimation=500
)
# Audio output
self.audio_out = audio.sink(48000, "", True)
# Connect the chain
self.connect(self.src, self.wbfm, self.lpf, self.audio_out)
def main():
tb = fm_receiver()
tb.start()
input("Press Enter to stop...")
tb.stop()
tb.wait()
if __name__ == '__main__':
main()
Ham radio applications
GNU Radio is particularly powerful for ham radio applications where existing software does not exist or does not meet your needs.
Narrowband FM — VHF/UHF amateur repeaters
Replace the WBFM Receive block with an NBFM Receive block for VHF/UHF repeater monitoring. Add a Frequency Xlating FIR Filter before the demodulator to select a specific repeater channel from the wide SDR bandwidth. This lets you monitor multiple repeaters simultaneously by running multiple parallel demodulator chains from the same RTL-SDR input.
SSB demodulation for HF
SSB demodulation in GNU Radio uses a Frequency Xlating FIR Filter (to shift the signal to baseband) followed by a Complex to Real block or a Hilbert transform. For HF operation with RTL-SDR enable direct sampling mode in the device arguments: osmosdr.source(args="rtl=0,direct_samp=2").
CW decoder
Build a CW decoder by: selecting a narrow bandwidth with a bandpass filter, applying power detection to find the CW key-on and key-off transitions, measuring timing to determine dit and dah lengths, and decoding against a Morse code lookup table. Several out-of-tree modules implement this — search for gr-morse in the GNU Radio community.
SSTV reception
Pipe the audio output of a GNU Radio SSB receiver to QSSTV via a virtual audio device. GNU Radio handles the HF reception and SSB demodulation, QSSTV handles the SSTV image decoding. This workflow is identical to using GQRX + QSSTV but gives you more control over the receive chain parameters.
Spectrum monitoring and recording
Record entire band segments as I/Q files using a File Sink block. A 2.4 MHz wide recording of the 20m band captures all activity simultaneously. Play back the file later and tune to any frequency within the recorded bandwidth. This is extremely useful for contest analysis — record the entire contest and review any QSO after the fact.
AX.25 packet radio with GNU Radio
GNU Radio can decode AX.25 packet radio frames directly, making it a software TNC for APRS and traditional packet without needing Direwolf or hardware TNCs. The gr-satellites out-of-tree module includes AX.25 decoders optimized for both 1200 baud AFSK and 9600 baud FSK.
Basic AX.25 / APRS receive chain
# Block chain for 1200 baud AFSK APRS (144.390 MHz):
# RTL-SDR Source (2.4 Msps, centered at 144.390 MHz)
# → Frequency Xlating FIR Filter (select 144.390 MHz channel)
# → NBFM Receive (12.5 kHz FM demodulation)
# → AFSK Demodulator (1200/2200 Hz tones → bits)
# → HDLC Framer (bits → AX.25 frames)
# → Message Debug (print decoded packets)
gr-satellites for satellite packet decoding
The gr-satellites project by Daniel Estévez EA4GPZ is the most comprehensive out-of-tree module for decoding amateur satellite telemetry. It supports AX.25, KISS, and dozens of satellite-specific protocols from OSCAR satellites, CubeSats, and LEO experimental satellites.
pip3 install --user construct requests
git clone https://github.com/daniestevez/gr-satellites.git
cd gr-satellites
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
sudo ldconfig
Connecting GNU Radio decoded packets to Direwolf
Output decoded AX.25 frames from GNU Radio as KISS frames over a TCP socket. Connect Direwolf (or any other AX.25 application) to this socket as a software TNC. This hybrid approach uses GNU Radio's superior signal processing for demodulation and Direwolf's established iGate and digipeater logic for the APRS application layer.
Satellite signal decoding
GNU Radio excels at satellite signal processing. The combination of flexible signal processing blocks, gr-satellites, and Gpredict for Doppler correction makes it the most capable open-source satellite decoding toolkit available.
Weather satellite APT reception (NOAA)
NOAA weather satellites transmit APT (Automatic Picture Transmission) images on ~137 MHz. The receive chain is straightforward:
# NOAA APT receive chain:
# RTL-SDR Source (1.024 Msps, ~137.5 MHz center)
# → Frequency Xlating FIR Filter (select NOAA channel)
# → WBFM Receive (demodulate the 50 kHz FM signal)
# → Resampler (to 20800 samples/second for APT)
# → File Sink (save for WXtoImg or noaa-apt decoder)
Linear transponder satellites (SSB/CW)
Many amateur OSCAR satellites have linear transponders that relay SSB and CW contacts. Receiving them requires Doppler-corrected SSB demodulation. Use Gpredict to update the GNU Radio center frequency via the Hamlib remote control interface, or write a Python script using the ephem library to calculate and apply Doppler correction in real time.
FM satellites — AO-91, AO-92
Several amateur satellites use FM transponders. The receive chain is a standard NBFM receiver with Doppler correction. The signal sweeps across several kHz during a pass as the satellite's velocity changes the received frequency.
Using gr-satellites for CubeSat telemetry
The gr-satellites module includes pre-built flowgraphs for decoding telemetry from hundreds of amateur CubeSats. Run the included example flowgraphs to receive and decode satellite telemetry during a pass. Decoded data uploads automatically to the SatNOGS network if configured.
Python scripting with GNU Radio
Every GNU Radio flowgraph is Python code. You can write GNU Radio applications directly in Python without using GRC — useful for automated scanning, headless operation, and integrating SDR processing into larger applications.
Running a flowgraph from Python
# GRC generates a .py file alongside every .grc file
# Run it directly:
python3 my_flowgraph.py
# Or make it executable:
chmod +x my_flowgraph.py
./my_flowgraph.py
Modifying a running flowgraph from Python
One of GNU Radio's most powerful features — you can change block parameters while the flowgraph is running. This is how Gpredict applies Doppler correction: it calls source.set_center_freq(new_freq) on the running flowgraph every second without stopping and restarting the signal chain.
import time
from gnuradio import gr
import osmosdr
class my_receiver(gr.top_block):
def __init__(self):
# ... setup blocks ...
self.src = osmosdr.source(args="rtl=0")
self.src.set_center_freq(145.800e6)
def retune(self, new_freq):
# Change frequency without stopping
self.src.set_center_freq(new_freq)
tb = my_receiver()
tb.start()
# Scan across a band
for freq in range(145000000, 146000000, 25000):
tb.retune(freq)
time.sleep(0.5) # Listen on each frequency for 0.5 seconds
tb.stop()
Reading decoded data from Python
Use a ZMQ Pub Sink block in your flowgraph to publish decoded messages. Connect to it from your Python application using PyZMQ to receive and process the decoded data in real time. This is how many GNU Radio-based monitoring systems work — the flowgraph does the signal processing, a Python application handles the higher-level logic.
Out-of-tree modules — extending GNU Radio
Out-of-tree (OOT) modules add new blocks to GNU Radio beyond those in the standard library. The community has created hundreds of OOT modules covering everything from specific satellite decoders to amateur digital modes.
Key OOT modules for ham radio
| Module | Description | Install |
|---|---|---|
| gr-satellites | Amateur satellite telemetry decoders for 100+ satellites | GitHub + cmake build |
| gr-osmosdr | RTL-SDR, HackRF, Airspy, SDRplay hardware support | apt install gr-osmosdr |
| gr-ax25 | AX.25 packet radio encoding and decoding | GitHub + cmake build |
| gr-ais | Marine AIS transponder decoder | GitHub + cmake build |
| gr-adsb | Aircraft ADS-B transponder decoder | GitHub + cmake build |
| gr-dsd | Digital voice decoder (P25, DMR, D-STAR audio) | GitHub + cmake build |
| gr-iridium | Iridium satellite phone signal decoder | GitHub + cmake build |
| gr-wspr | WSPR beacon encoder and decoder | GitHub + cmake build |
Installing an OOT module
git clone https://github.com/[author]/gr-[module].git
cd gr-[module]
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make -j$(nproc)
sudo make install
sudo ldconfig
# Rebuild GRC block cache
grcc -d ~/.grc_gnuradio
Finding OOT modules
The GNU Radio community maintains a list of OOT modules at the GNU Radio wiki (wiki.gnuradio.org/index.php/OutOfTreeModules). GitHub is also a good source — search for "gr-" followed by the protocol or technology you are interested in.
Performance optimization
GNU Radio can be CPU-intensive, especially at high sample rates with multiple processing chains running simultaneously.
Use the correct data types
Processing in float or complex float is faster than double precision. Make sure all your blocks use gr_complex (complex float) for SDR processing rather than complex double. Check block data types in GRC — the wire colours show the data type.
Decimation as early as possible
Reduce sample rate as early as practical in the flowgraph. Processing 2.4 Msps through many blocks is much more expensive than decimating to 48 ksps immediately and processing the lower-rate signal. Apply the channel selection filter and decimation right after the hardware source.
VOLK — vector-optimised library
VOLK is included with GNU Radio and provides CPU-optimised implementations of common signal processing operations using SIMD instructions (SSE, AVX). Run the VOLK profiler once to select the best implementation for your specific CPU:
# Takes 5-15 minutes to run
volk_profile
# Results saved to ~/.volk/volk_config
# GNU Radio automatically uses the optimised kernels afterward
Affinity and scheduling
For real-time SDR work on a busy system, set GNU Radio's process priority: sudo nice -n -15 python3 my_flowgraph.py. This gives the signal processing priority over other processes and reduces audio dropouts and buffer overflows.
GNU Radio vs GQRX vs OpenWebRX
| Feature | GNU Radio | GQRX | OpenWebRX |
|---|---|---|---|
| Purpose | SDR development framework | Desktop SDR receiver | Browser-based SDR server |
| Learning curve | Very high | Low | Low |
| Custom decoders | Yes — build anything | No | Via plugins only |
| Ready to use | No — requires flowgraph | Yes | Yes |
| Remote access | No (without extra work) | No | Yes — native browser |
| Multiple users | No | No | Yes |
| Python scripting | Yes — core capability | Limited (remote control) | No |
| Signal analysis | Full — constellation, eye diagram | Waterfall and spectrum only | Waterfall only |
| Satellite Doppler | Yes — via Python API | Yes — via Gpredict | No |
| Built on GNU Radio | Is GNU Radio | Yes | No |
The right tool for each job
- Everyday monitoring — GQRX or OpenWebRX. No reason to use GNU Radio for simply listening.
- Sharing with others / remote access — OpenWebRX. Browser-native, multiple users, easy setup.
- Custom decoder development — GNU Radio. If no existing software decodes what you want, build it here.
- Satellite telemetry — GNU Radio + gr-satellites. The most capable option by far.
- SDR research and education — GNU Radio. Nothing else gives the same level of insight into signal processing.
- Audio piping to existing decoders — GQRX is simpler. GNU Radio gives more control but requires more work.
Troubleshooting common problems
GRC won't launch — import errors
- Check GNU Radio Python path:
python3 -c "import gnuradio; print(gnuradio.__version__)" - If this fails, GNU Radio Python bindings are not installed or not on the Python path
- Set PYTHONPATH:
export PYTHONPATH=/usr/local/lib/python3/dist-packages: - Try reinstalling:
sudo apt install --reinstall gnuradio python3-gnuradio
Flowgraph runs but no audio
- Check the Audio Sink sample rate matches the actual output rate from your signal chain
- Add a Throttle block before the Audio Sink if not using real hardware — without it the flowgraph runs faster than real time and overflows the audio buffer
- Check the audio device name in the Audio Sink — try an empty string to use the default device
- Verify signal is reaching the Audio Sink by adding a QT GUI Level Meter block before it
Buffer overflow / underflow messages
- Buffer overflow (O): downstream processing cannot keep up — reduce sample rate or simplify the flowgraph
- Buffer underflow (U): audio buffer runs dry — increase the audio buffer size or reduce CPU load
- Run the VOLK profiler to optimise signal processing:
volk_profile - Close other CPU-intensive applications while running GNU Radio
RTL-SDR source not found in GRC
- Verify gr-osmosdr is installed:
python3 -c "import osmosdr" - Check DVB-T driver blacklist:
cat /etc/modprobe.d/blacklist-rtl.conf - Test the dongle:
rtl_test -t - Add user to plugdev group:
sudo usermod -a -G plugdev
OOT module blocks not appearing in GRC
- Rebuild the GRC block cache:
grcc -d ~/.grc_gnuradio - Check the module installed to the correct prefix: the cmake prefix must match where GNU Radio is installed
- Run
ldconfigafter installing:sudo ldconfig - Check
GRC_BLOCKS_PATHenvironment variable includes the OOT module path
Frequently asked questions
Do I need to know signal processing to use GNU Radio?
Some understanding of signal processing fundamentals is very helpful — concepts like sample rate, decimation, filters, and modulation types. You can build useful flowgraphs by following tutorials without deep mathematical knowledge, but debugging problems and building custom decoders requires understanding what the blocks actually do. The GNU Radio tutorials at wiki.gnuradio.org are an excellent starting point and assume no prior SDR knowledge.
What is the difference between GNU Radio 3.8, 3.9, and 3.10?
GNU Radio 3.10 is the current stable major version and requires Python 3. GNU Radio 3.8 and 3.9 were previous stable versions that are now mostly obsolete. If you install from your distribution's repository on Ubuntu 22.04 or later you will get a 3.10.x version. Flowgraphs built for older versions may need minor modifications to run on 3.10 — mostly API changes in how blocks are imported in Python.
Can GNU Radio transmit as well as receive?
Yes — with transmit-capable hardware like HackRF, LimeSDR, PlutoSDR, or USRP, GNU Radio can transmit. Use an osmosdr.sink block instead of a source. Implementing a transmitter requires the same signal processing knowledge as a receiver but in reverse — modulate your signal, apply the appropriate filters, and route to the hardware sink. Always verify your transmissions are legal for your license class and intended frequency before transmitting.
Is GNU Radio used in professional / commercial applications?
Yes extensively — GNU Radio is used in military communications research, wireless standards development, academic signal processing research, and commercial SDR product development. Major organizations including DARPA, NASA, and numerous universities use GNU Radio. The fact that it is open source and free makes it accessible for professional research and development without licensing fees.
How do I decode D-STAR or DMR with GNU Radio?
The gr-dsd out-of-tree module implements digital voice decoding for P25, DMR, D-STAR, and other protocols. Install it from GitHub, then build a flowgraph that demodulates the FM signal and pipes the output to the DSD decoder block. Note that decoding private or encrypted digital voice communications may be illegal in your jurisdiction regardless of the technical feasibility.
What is the best way to learn GNU Radio?
Start with the official GNU Radio tutorials at wiki.gnuradio.org — they cover the fundamentals progressively from a simple audio flowgraph up to SDR receivers. PySDR (pysdr.org) by Marc Lichtman is an excellent free textbook covering both the signal processing theory and GNU Radio implementation. The GNU Radio Conference presentations on YouTube cover advanced topics once you have the basics. Expect to spend 10–20 hours before you feel comfortable building your own flowgraphs from scratch.