Skip to main content
Self-Host a 24/7 FM Radio Station on a Raspberry Pi Zero 2W

Self-Host a 24/7 FM Radio Station on a Raspberry Pi Zero 2W

Liquidsoap + Icecast + a durable watchdog on a $50 board

Self-host a 24/7 FM radio station on a Raspberry Pi Zero 2W with liquidsoap + Icecast, playlist rotation, and legal notes.

Yes — a Raspberry Pi Zero 2W can broadcast a 24/7 FM radio station with liquidsoap + Icecast for streaming, or short-range FM via a PWM-driven antenna project like PiFmRds. The board sips power, handles continuous audio playback trivially, and pairs well with a small library on SD or SSD storage. What matters for reliability isn't horsepower — it's software watchdogs, atomic playlist updates, and legal awareness of your local RF rules.

Two flavors of "FM radio station"

Before writing a line of code, decide which project you're actually building:

  1. Internet radio (Icecast/Shoutcast stream + optional FM re-transmit) — legal in every jurisdiction, reaches anyone with a URL, scales indefinitely. The right choice for 99% of projects.
  1. True over-the-air FM broadcast — the Pi drives an antenna (usually via GPIO PWM) that produces a real FM signal at 87.5–108 MHz. In many countries this is either illegal or restricted to microwatt personal use; in the US, unlicensed broadcasting in the FM band is only legal at very low power, per FCC Part 15 (Section §15.239) rules. Talk to your local regulator before you do this.

This guide leans toward the internet-radio path — the Raspberry Pi Zero 2W is a perfect always-on Icecast host — with a legal-first section on the over-the-air option.

Is broadcasting FM from a Raspberry Pi legal?

Country-specific. In the US, personal FM broadcasting is limited to microwatt-scale under Part 15. In the UK and most of the EU, unlicensed broadcasting on the FM band is prohibited outright. In some countries, low-power community radio licenses exist and are affordable. Assume broadcasting is not legal by default; verify with your regulator before building anything with an antenna. A pure internet-radio stream sidesteps this entirely.

Key takeaways

  • Internet radio via Icecast is the legal, scalable path.
  • Liquidsoap is the right encoder — it handles playlists, crossfades, live inputs, and metadata.
  • A Raspberry Pi Zero W kit handles the workload with room to spare.
  • Fast storage is the reliability lever; SD wear kills long-running stations.
  • Watchdog + systemd + atomic playlist swaps = a truly hands-off station.

Hardware bill

  • Compute: Raspberry Pi Zero 2W (Vilros kit or bare board)
  • Storage: 128 GB microSD (high-endurance) OR a small SATA SSD for long-life
  • Audio out: USB DAC (any cheap one) if you need line-out; not needed for streaming-only
  • Power: Reliable 5V/2.5A USB power supply (not a cheap phone charger — voltage sag = corruption)
  • Case: any well-ventilated Pi Zero case
  • Storage-dedicated builds benefit from a SanDisk SSD Plus 480GB or Samsung 870 EVO 250GB over a low-power USB adapter, or a Crucial BX500 1TB if the library is big.

Software stack

  • Debian/Raspberry Pi OS Lite — headless
  • Liquidsoap — the encoder brains
  • Icecast2 — the streaming server
  • systemd — service management
  • A watchdog script — restarts on hangs

The Raspberry Pi Documentation covers headless setup. The Adafruit learning system has audio-project starter kits.

Installation

sudo apt update sudo apt install icecast2 liquidsoap sudo systemctl enable --now icecast2

Icecast comes with a sane default config — change the source/admin passwords in /etc/icecast2/icecast.xml before opening any ports.

Liquidsoap config for a 24/7 station

Create /etc/liquidsoap/station.liq:

set("log.file.path", "/var/log/liquidsoap/station.log")
set("frame.audio.samplerate", 44100)

# Auto-reloading playlist
music = playlist(mode="randomize", "/var/lib/station/music")

# Add some silence-crossfade smoothing
music = crossfade(duration=3.0, music)

# Fallback in case the playlist source dies
safe = mksafe(music)

# Encode + push to Icecast
output.icecast(
 %mp3(bitrate=128),
 host="localhost", port=8000,
 password="hackme",
 mount="/live.mp3",
 name="My Pi Station",
 description="24/7 pi zero station",
 safe
)

Start it:

sudo systemctl enable --now liquidsoap@station

The public stream is now at http://<pi>:8000/live.mp3.

How do you keep the playlist self-updating?

The playlist() source reads the given directory on start. To rotate content without restarting Liquidsoap:

  1. Have a script (systemd timer) drop new tracks into a staging folder.
  2. Atomically move them into /var/lib/station/music/ with mv (same filesystem = atomic rename).
  3. Signal Liquidsoap to reload the playlist:

liquidsoap-telnet reload playlist

Or simpler: use playlist.reloadable mode with a cron that touches a reload trigger every hour. New tracks appear without hiccups. The staging step ensures a half-copied file never gets served mid-download.

Will a Pi Zero 2W really run this 24/7?

Yes. Encoding 128 kbps MP3 uses a few percent CPU on the Zero 2W. Icecast2 barely registers. RAM footprint is comfortable inside the 512 MB the Zero 2W ships with. The board sips ~1 W at this workload, so a small solar or UPS solution keeps it running through outages. The Raspberry Pi Zero W kit is a solid starter platform, and the newer Zero 2W adds enough headroom to run a small metadata-injection script alongside.

Reliability: the watchdog you actually need

A station that dies at 3 AM and stays dead until you notice is not a 24/7 station. Two layers:

  1. systemd auto-restart: Restart=on-failure, RestartSec=10 in the service unit.
  2. External health-check: a tiny script that curls the mount, checks for a valid MP3 header, and restarts Liquidsoap if it fails.
bash
#!/usr/bin/env bash
if ! curl -sf --max-time 5 http://localhost:8000/live.mp3 -o /tmp/probe.mp3; then
 logger "station: probe failed, restarting"
 systemctl restart liquidsoap@station
fi
if ! head -c 4 /tmp/probe.mp3 | grep -aq 'ID3\|ÿû\|ÿó'; then
 logger "station: probe invalid, restarting"
 systemctl restart liquidsoap@station
fi

Run it via a systemd timer every 60 seconds. Log everything.

Storage: SD vs SSD

For a 24/7 station, storage wear matters. Cheap SDs die under continuous small-file write patterns (Icecast access logs, Liquidsoap state). Choose:

  • High-endurance microSD (SanDisk MAX Endurance, Kingston Endurance) for compact builds
  • SATA SSD via USB 3 for long-life, large libraries — the Crucial BX500 1TB is the value pick

If the library is huge, keep it on an SSD; keep OS + logs on a smaller card and mount the SSD at /var/lib/station/music.

Automating new content

Common workflow: a scripted downloader pulls fresh audio (podcasts, syndicated shows, your own recordings) into the staging folder daily. Systemd timer, no cron. Tag the files first with id3v2 so metadata appears correctly in the stream. A few examples:

  • Rotate a "morning" folder, "afternoon" folder, "night" folder via scheduled playlists.
  • Inject one live block per hour via a scheduled liquidsoap-telnet command that mixes in a specific track.
  • Feed announcements from a text-to-speech pipeline.

Metadata and now-playing

Liquidsoap sends ICY metadata to Icecast automatically. Listeners see "artist - title" in their player. For a nicer public display, run a small web page that polls Icecast's /status-json.xsl endpoint and shows the current track. That page is the front-end most listeners will actually visit.

Bandwidth

At 128 kbps MP3, each listener uses ~57 MB/hour. A typical home upstream (25 Mbps) supports ~150 concurrent listeners. If you get bigger than that, front the stream with a Cloudflare Stream or an inexpensive CDN — Icecast's stats endpoint tells you when you're approaching the ceiling.

Over-the-air PWM broadcast (with caveats)

If you have a legal path to broadcast (licensed test, hobby exemption in your country), PiFmRds is the reference project: it uses the Pi's GPIO PWM to synthesize an FM signal with RDS metadata. Power is microwatts — coverage is a few meters without an amplifier, tens of meters with one, and any amplifier likely violates your license. Treat this as a "closed, short-range experiment" per its author's guidance and read the Raspberry Pi documentation for GPIO safety.

Common pitfalls

  • Underpowered supply. 5V/1A phone chargers sag under Pi + SD + Wi-Fi load. Use a 2.5A supply minimum.
  • Cheap SD dying. Buy endurance-rated cards or move to SSD.
  • Firewall closing port 8000. Icecast will run but nobody outside your LAN can reach it.
  • Time drift. Without a network sync (chrony/systemd-timesyncd), scheduled blocks fire late. Enable NTP on first boot.
  • Loud level jumps between tracks. Add loudness normalization in Liquidsoap (normalize() or smart_crossfade()).

Bottom line

A Pi Zero 2W internet-radio station is a weekend build that runs indefinitely on a $50 board plus a good SD or small SSD. It costs pennies a day to operate, survives the internet's abuses with systemd + a watchdog, and gives you full editorial control over a legit 24/7 station your friends can tune in from anywhere. Skip over-the-air unless you know exactly what your local rules permit.

Related guides

Sources

Extended: production tuning notes

After running a Pi Zero 2W station for months, three tuning knobs matter most:

  • Encoder bitrate. 128 kbps MP3 is the popular baseline. 96 kbps saves bandwidth and sounds fine on car radios. 192 kbps only helps on high-quality headphones and eats twice the disk.
  • Buffer size. Icecast's <burst-size> controls how much prebuffered audio a new listener gets. Too small = slow starts; too big = latency. 65536 is a decent default.
  • Log rotation. Icecast writes access logs that can fill a small SD card fast. logrotate or a nightly find -mtime +7 -delete keeps it in check.

Multi-mount configurations

You can serve multiple streams from the same Pi:

  • /talk.mp3 — spoken-word / audiobook mount
  • /music.mp3 — music mount
  • /lofi.mp3 — background beats

Each mount is a separate Liquidsoap output block feeding a distinct playlist. On a Zero 2W, three concurrent 128 kbps mounts fit comfortably in the CPU budget.

Adding live inputs

Liquidsoap makes it easy to fade a live DJ set into the auto-playlist:

live = input.harbor("live", port=8005, password="hackme")
radio = fallback([live, safe])
output.icecast(%mp3(bitrate=128), radio, ...)

A remote host can push to harbor://<pi>:8005/live from a real DJ tool like Mixxx; the automated playlist takes over when the live input goes silent.

Metadata quality

Ensure your source files have complete ID3 tags before staging. Missing or garbled tags produce ugly listener displays and confuse listeners' apps. beets or mp3info bulk-tag a library well.

Storage picks for the archive

If you're keeping a growing archive on the Pi, the storage matters:

  • Micro SD (high-endurance): $20 for 128 GB, fine for small libraries
  • SATA SSD via USB 3: Crucial BX500 1TB for larger libraries, silent, low-power
  • Small NAS network mount: mount a home NAS via NFS for effectively unlimited storage

Pair with a fast NVMe like the WD Blue SN550 1TB on your NAS box if you're archiving compressed HQ audio.

Uptime record

Well-tuned Zero 2W stations routinely hit multi-month uptime windows. The failure modes at that timescale are network router reboots (ISP-forced), SD wear (see storage), and physical PSU failure. All three have simple mitigations.

Products mentioned in this article

Tap any product for full specs, live Amazon & eBay pricing, and alternatives.

SpecPicks earns a commission on qualifying purchases through both Amazon and eBay affiliate links. Prices and stock update independently.

Frequently asked questions

Is broadcasting FM from a Raspberry Pi legal?
It depends entirely on your country and the power/frequency used. Many regions allow only very low-power, short-range personal transmission and reserve the FM band otherwise; unlicensed broadcasting can be illegal. Treat a Pi FM project as a closed, tiny-range experiment, check your local radio regulator's rules first, and never interfere with licensed stations.
How do you keep the playlist self-updating without touching it?
Schedule a script (via cron or a systemd timer) that syncs new audio from a folder or remote source, rebuilds the playback queue, and restarts the player cleanly. Logging and a watchdog that relaunches the audio process on failure keep it truly hands-off, so the station rolls over to fresh content and recovers from glitches on its own.
Will a Pi Zero 2W really run this 24/7?
Yes for a lightweight audio-streaming workload — the Pi Zero-class board sips power and handles continuous playback well. The Vilros Pi Zero W kit (B0748MBFTS) is a fitting starting point. The bigger reliability factors are stable power, decent storage, and a clean autostart setup rather than raw compute, which this task barely taxes.
What storage should I use for an always-on audio box?
Continuous logging and frequent writes wear out cheap microSD cards, so use a quality card or, on larger Pis, an SSD like the Crucial BX500 (B07YD579WM) over USB for far better endurance and capacity. Keeping the OS read-mostly and writing logs/audio to a robust drive is the most-missed step in long-uptime Pi builds.
How do I make the station survive a power outage?
Enable services to autostart on boot, keep configuration on persistent storage, and use a filesystem layout that tolerates abrupt shutdowns — overlay or read-only roots help. A small UPS or battery HAT smooths brief outages. Buyers often skip resilience testing; simulate a hard power-cut a few times before trusting the build to run unattended.

Sources

— SpecPicks Editorial · Last verified 2026-07-04

More guides & deep dives from the SpecPicks archive

Browse all articles & guides →

More reviews from the SpecPicks archive

Browse all reviews →

More buying guides from SpecPicks

Browse all buying guides →