Skip to content

Significant changes#12

Open
kindsouls wants to merge 2 commits into
oweitman:masterfrom
kindsouls:master
Open

Significant changes#12
kindsouls wants to merge 2 commits into
oweitman:masterfrom
kindsouls:master

Conversation

@kindsouls

Copy link
Copy Markdown

Changes from the original (2019) package

Bug fixes

The original code had multiple outright bugs that prevented reliable operation:

Bug Original Fixed
File handle leak open(os.devnull, 'w') at module level, never closed subprocess.DEVNULL
Wrong process API .kill() + os.waitpid() mixing two incompatible interfaces .terminate() → .wait(timeout=5) → .kill()
Wrong ALSA profile PROFILE=a2dp PROFILE=a2dp-source (Pi is the sender)
Relative config path CONFIG_FILE = 'bt-devices' (broke if WorkingDirectory changed) Absolute /etc/pyserver/bt-devices
D-Bus path bounds check len(parts) >= 4 then accessed parts[4] — off-by-one len(parts) >= 5
Python 2 relics from future import absolute_import, print_function, unicode_literals Removed
No logging dbg = False / bare print() — nothing went to journald logging module writing to stdout, captured by systemd
No shutdown handler Squeezelite processes left running when daemon stopped SIGTERM/SIGINT handlers that cleanly stop all players
Deprecated systemd directive StandardOutput=syslog StandardOutput=journal
Missing service dependency Monitor could start before bluealsa was ready After=bluezalsa.service + Wants=bluezalsa.service
bluealsa binary not found Build defaulted to /usr/local/bin, service pointed at /usr/bin Added --prefix=/usr to build instructions
Wrong bluealsa flag -p a2dp-source (old syntax, rejected by newer versions) --profile=a2dp-source
Python deps with sudo pip sudo pip3 install dbus-python sudo apt-get install python3-dbus python3-gi
64-bit Pi OS path wrong Only documented armhf ALSA plugin path Both arm-linux-gnueabihf and aarch64-linux-gnu paths, auto-detected
No Bluetooth auto-power Adapter powered off after boot, required manual bluetoothctl power on AutoEnable=true in /etc/bluetooth/main.conf

Detection checks (in order): WirePlumber process, system-level PipeWire service, PipeWire socket at /run/user/1000/pipewire-0. Override with FORCE_AUDIO_BACKEND=pipewire|bluealsa sudo ./install.sh.


Configuration

The bt-devices config file was a flat MAC=Name text file. It is now an INI format with per-device options:

# Old format
AA:BB:CC:DD:EE:FF=Livingroom

New format

[AA:BB:CC:DD:EE:FF]
name = Livingroom
codec = aptx # optional; bluealsa only
lms = 192.168.1.10 # optional; omit to auto-discover

  • codec — selects A2DP audio codec (aptX, AAC, SBC-XQ, etc.) on bluealsa
  • lms — pins the LMS server address for installs where mDNS auto-discovery doesn't work (VLANs, etc.)
  • Hot-reload — the file is re-read on every connection event; changes take effect without restarting the service
  • Auto-migration — on first start after an update, the daemon detects the old flat format, converts to INI automatically, and saves the original as bt-devices.bak
  • Validation — malformed MAC addresses and missing name fields are logged and skipped rather than silently passed to squeezelite

Security hardening

Neither service had any sandboxing. Both now have systemd security directives:

btspeaker-monitor.service (unprivileged lms user — tighter restrictions):

  • NoNewPrivileges=yes
  • ProtectSystem=strict — filesystem read-only except for carve-outs
  • ReadWritePaths=/etc/pyserver — allows config migration write
  • ProtectHome=yes, PrivateTmp=yes
  • Wants= instead of Requires= for bluezalsa — service starts on PipeWire systems where bluezalsa isn't installed

bluezalsa.service (runs as root, conservative):

  • NoNewPrivileges=yes, ProtectHome=yes, PrivateTmp=yes
  • ProtectSystem and RestrictAddressFamilies intentionally omitted — bluealsa needs direct kernel BT socket access

Installer and tooling

The original had no installer. Everything was manual steps in the README.

install.sh — single-command installer:

  • Auto-detects PipeWire vs bluealsa
  • Tries apt install bluealsa first, builds from source as fallback
  • Detects Pi architecture (armhf / aarch64) for correct ALSA plugin path
  • Creates lms system user and adds to audio group
  • Deploys all files, sets ownership and permissions
  • Configures Bluetooth auto-power-on
  • Enables and starts services
  • Writes an install manifest for the uninstaller
  • Idempotent — safe to re-run

install.sh --add-device — interactive pairing wizard:

  • Scans for nearby BT devices
  • Runs pair / trust / connect via bluetoothctl
  • Prompts for player name and optional LMS server address
  • Writes the INI entry to bt-devices and restarts the monitor

install.sh --status — live system view (no sudo needed):

  • Service running state with uptime
  • All configured devices from bt-devices
  • Which BT devices are currently connected
  • Running squeezelite PIDs with full command lines
  • Install date, architecture, and audio backend from the manifest

install.sh --update — redeploys source files and restarts services without a full rebuild

uninstall.sh — manifest-driven uninstaller:

  • Reads /var/lib/squeezelite-bluetooth/install.manifest to remove exactly what was installed
  • Falls back to hardcoded defaults if manifest is missing
  • Stops/disables services, removes files, reverts AutoEnable=true, and optionally removes the lms user and bluealsa
  • Warns if bt-devices has configured speaker entries before removing it
  • --yes flag for scripted/non-interactive removal

Documentation

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Labels

    None yet

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    1 participant