See also: Documentation index · Bluetooth pairing · Troubleshooting
- Linux host with working Bluetooth and audio output. Raspberry Pi is the primary target, but not a hard requirement.
- For Raspberry Pi, a Pi 3 or newer is a practical baseline; Pi 4/5 is not required.
- Raspberry Pi OS Bookworm or Debian Bookworm, 32-bit or 64-bit. Other Debian-like systems can work if they provide compatible BlueZ/BlueALSA packages.
- Bluetooth adapter, built-in or USB.
- ALSA playback device: USB DAC, HAT, HDMI, or built-in audio. USB DAC/HAT is recommended for quality.
- Python 3.11+,
systemd, system D-Bus, BlueZ, BlueALSA, and ALSA utilities. qrencodeis optional but recommended for the phone login QR code.
Bluezard does not require Raspberry Pi hardware, a desktop session, PipeWire, PulseAudio, or a 64-bit OS. The important pieces are BlueZ for Bluetooth, BlueALSA for A2DP audio, ALSA for playback, systemd/D-Bus for service and Bluetooth integration, and Python 3.11 for the web manager.
git clone https://github.com/MatFaes/Bluezard.git
cd Bluezard
sudo bash scripts/install.shThe installer detects your system and asks:
- Bluetooth adapter — auto-selected if only one is present
- ALSA output card — lists available cards, select your DAC
- Network binding — localhost only, or all interfaces (LAN access)
- Auth token — if LAN access is chosen, option to generate a token
At the end, the installer displays the web UI URL (with token if generated).
sudo bash scripts/install.sh --non-interactive \
--hci=hci0 \
--card=1 \
--host=0.0.0.0sudo bash /opt/bluezard/scripts/update.shPulls the latest release from GitHub, redeploys files, and restarts the service.
The .env (your configuration) and /var/lib/bluezard/state.json runtime state
are never touched during an update.
Force reinstall even if already up to date:
sudo bash /opt/bluezard/scripts/update.sh --forceAdmin configuration is stored in /opt/bluezard/.env (created from .env.example
at install). Settings changed from the UI are stored separately in
/var/lib/bluezard/state.json.
| Variable | Default | Description |
|---|---|---|
BLUEZARD_HOST |
127.0.0.1 |
Bind address (0.0.0.0 for LAN access) |
BLUEZARD_PORT |
8088 |
HTTP port |
BLUEZARD_TOKEN |
(empty) | Auth token — empty disables authentication |
BLUEZARD_REQUIRE_TOKEN |
false |
When a token is set, also require it for localhost. Enabled by the installer for LAN binding |
BLUEZARD_STATE_DIR |
/var/lib/bluezard |
Writable runtime state directory |
BLUEZARD_DEFAULT_PCM |
(empty) | Default ALSA output PCM, set by the installer |
BLUEZARD_EXCLUSIVE_SINK |
true |
Disconnect other devices when a new device starts streaming |
BLUEZARD_PLAYER_MODE |
connected |
connected runs players only while devices are connected; always_ready pre-starts players for trusted A2DP devices |
BLUEZARD_LOG_LEVEL |
INFO |
DEBUG / INFO / WARNING / ERROR |
BLUEZARD_BLUEZ_ADAPTER |
hci0 |
HCI adapter name |
BLUEZARD_DEBUG |
false |
Verbose debug logging and uvicorn reload |
After editing .env:
sudo systemctl restart bluezardhttp://<bluezard-host>:8088
If an auth token is set, the UI prompts for it when needed. You can also append it as a query parameter on first visit; the browser stores it as a cookie and cleans the URL:
http://<bluezard-host>:8088?bluezard_token=<token>
The install summary prints the full URL with token if one was generated.
To show the URL and QR code again later on the Pi:
bash ~/Bluezard/scripts/show-qr.sh --host rpi-player.localBluezard is a responsive PWA with sidebar navigation on desktop and a compact header plus bottom player bar on mobile.
| View | What you do there |
|---|---|
| Dashboard | Monitor playback, stream metrics, Audio Pipeline; start pairing |
| Devices | Connect, disconnect, forget devices; open device details |
| Settings | Default output, one-device-at-a-time mode, advanced diagnostics |
Dashboard during playback — AVRCP metadata and BlueALSA stream metrics
More screenshots (Devices, Settings, mobile): docs/README.md.
Install Bluezard to the home screen from the browser menu. The auth token is stored persistently after the first QR or query-parameter login.
Use scripts/deploy-dev.sh for fast iteration against a remote Pi:
# Fast deploy: copies static files + Python modules + restarts
bash scripts/deploy-dev.sh pi@raspi.local
# Full deploy: pip reinstall (needed when deps change)
bash scripts/deploy-dev.sh pi@raspi.local --fullThe script handles rsync, file placement into the installed package, and service restart automatically. Static-only changes (CSS/JS/HTML) don't require a full reinstall.
python3 -m venv venv
source venv/bin/activate
pip install -e .
# Requires the current user to be in the bluetooth group
sudo usermod -aG bluetooth $USER
# Log out and back in, then:
bluezard# Status
systemctl status bluezard bluealsa bluetooth
# Logs
journalctl -fu bluezard
journalctl -fu bluealsa
# Restart
sudo systemctl restart bluezardIf accessing over LAN with BLUEZARD_HOST=0.0.0.0:
sudo ufw allow 8088/tcp comment 'Bluezard'Set a BLUEZARD_TOKEN to prevent unauthorised access on untrusted networks.
sudo bash /opt/bluezard/scripts/uninstall.sh