This document details the internal architecture, service management, and advanced configuration of BirdNET-PiPy.
birdnet-service.sh: The master orchestration script. managed by systemd. It handles:- Docker container lifecycle
- Audio backend detection and startup (PulseAudio vs PipeWire)
- Auto-updates via git
- Includes PulseAudio configs (
system.pa,daemon.conf) for running in system-wide mode on RPi OS Lite. - Icecast streaming server configuration.
For audio architecture details, see Audio Architecture in the Architecture docs.
The system runs as a standard systemd service named birdnet-pipy.
sudo systemctl start birdnet-pipy # Start
sudo systemctl stop birdnet-pipy # Stop
sudo systemctl restart birdnet-pipy # Restart
sudo systemctl status birdnet-pipy # Check StatusService Controller Logs (Wrapper script output):
journalctl -u birdnet-pipy -fApplication Logs (Inner container output):
cd ~/BirdNET-PiPy
docker compose logs -f [container_name]
# containers: main, api, model-server, frontend, icecastYou can trigger maintenance tasks by touching flag files, avoiding full reboots.
| Trigger File | Action | Description |
|---|---|---|
data/flags/restart-backend |
Restart | Restarts all Docker containers. Useful after config changes. |
data/flags/update-requested |
Update | Runs install.sh --update which syncs code, rebuilds images, and updates system configs. |
Example:
# Trigger an update (content is the target branch)
echo "main" > ~/BirdNET-PiPy/data/flags/update-requestedBirdNET-PiPy supports two update channels, configurable in Settings:
| Channel | Branch | Description |
|---|---|---|
| Release | main |
Stable releases (default) |
| Latest | staging |
Newest features, may be less stable |
When you trigger an update, the system checks for updates from the configured channel's branch.
When an update is triggered, install.sh --update performs:
- Stops Docker containers
- Fetches and syncs to the target branch (git fetch + checkout + reset)
- Rebuilds Docker images
- Updates system configs (PulseAudio, systemd service, sudoers)
- Exits for systemd to restart the service
Manual update (current branch):
cd ~/BirdNET-PiPy && sudo ./install.sh --updateManual update (specific branch):
cd ~/BirdNET-PiPy && sudo ./install.sh --update --branch stagingNote: For existing installations before this feature was added, run sudo ./install.sh once to update the sudoers configuration for automatic updates.
# Verify PulseAudio is running on host
pactl info
# List available audio sources
pactl list sources short# Check if Icecast is receiving audio
curl -s http://localhost:8888/status-json.xsl | grep -o '"listeners":[0-9]*'
# Test stream directly
curl http://localhost:8888/stream.mp3 --max-time 3 -o /dev/null && echo "Stream OK"Icecast Web Interface: http://localhost:8888/status.xsl
Set environment variable before starting containers:
export STREAM_BITRATE=192k # Default is 128k
docker compose up -dBy default, a random 16-character password is generated each time the Icecast container starts. This is secure but means the password changes on restart.
To set a persistent password, set the environment variable:
export ICECAST_PASSWORD=your_secure_password
docker compose up -dNote: The static deployment/audio/icecast.xml file is not used at runtime. The startup script generates a secure config dynamically.