Operations
Day-to-day management of a running station.
Checking Status
Quick status — what's playing, are services up:
systemctl status mpd icecast2 nginx pi3radio song-logger
mpc status
The web UI also shows a health indicator (green/amber/red dot) in the header, backed by the /api/health endpoint which reports load, disk, NAS mount status, and service states.
Deploying Changes
All changes are deployed from your development machine — never edit files directly on the Pi. The workflow:
- Make changes locally
- Test in staging (mock data mode, no API keys needed)
- Promote to production
# Push to staging (port 8080, mock data)
rsync -av staging/ pi-user@your-pi:/var/www/radio-staging/
# Promote staging to production
cp -r staging/ public/
rsync -av public/ pi-user@your-pi:/var/www/radio/public/
# Deploy backend changes
rsync -av server/ pi-user@your-pi:/var/www/radio/
ssh pi-user@your-pi "sudo systemctl restart pi3radio"
Restarting Services
Restart the Python API and reload Nginx:
sudo systemctl restart pi3radio
sudo systemctl reload nginx
Restart MPD (will briefly interrupt the stream):
sudo systemctl restart mpd
Recovery After Power Loss
After a power cut or reboot, the NAS mount may not come back automatically. Run this sequence:
sudo mount -a # remount NAS
sudo systemctl restart mpd # restart MPD
/usr/local/bin/radio_scheduler.sh # re-run scheduler to resume programming
Log Files
| Log | Contents |
|---|---|
/var/log/radio_playlist.log | Every song played (4 lines per song) |
/var/log/radio_schedule.log | Hourly scheduler decisions |
/var/log/mpd/mpd.log | MPD errors and events |
/var/log/icecast2/error.log | Icecast errors |
/var/log/nginx/error.log | Nginx errors |
Tail the song log live:
tail -f /var/log/radio_playlist.log
Last 20 songs played:
grep "NOW PLAYING" /var/log/radio_playlist.log | tail -20
Database Backups
Pull a copy of the database to your local machine:
rsync pi-user@your-pi:/var/www/radio/db.sqlite3 ./backups/db_$(date +%Y%m%d_%H%M%S).sqlite3
Query tagged songs from a local backup:
sqlite3 backups/db_latest.sqlite3 \
"SELECT s.artist, s.title, t.tag FROM songs s JOIN tags t ON s.id = t.song_id ORDER BY t.tag, s.artist;"
Song Tagging
The web UI lets you tag any song in the recent playlist. Tags are stored in SQLite and used by the scheduler and stats views.
| Tag | Effect |
|---|---|
| Favourite | Marks the song as a keeper |
| Review | Flag to listen again before deciding |
| Live | Marks as a live recording |
| Bad MP3 | Flags poor quality rips |
| Duplicate | Flags duplicates in the library |
| Eject | Adds to exclude list — never plays again |
Useful API Calls
# What's playing right now
curl http://your-pi/api/playlist | python3 -m json.tool
# System health
curl http://your-pi/api/health | python3 -m json.tool
# All favourites
curl "http://your-pi/api/tags?tag=Favourite"
# Export full play history as CSV
curl http://your-pi/api/export -o plays.csv
Keyboard Shortcuts
The web player supports keyboard shortcuts when focused in a browser:
| Key | Action |
|---|---|
Space | Play / pause |
→ | Skip to next track |
F | Tag current track as Favourite |
R | Tag current track as Review |
L | Tag current track as Live |