Skip to content

Systemd integration

borine edited this page Jul 24, 2022 · 35 revisions

Using BlueALSA with systemd

Introduction

Systemd (https://www.freedesktop.org/wiki/Software/systemd/) is now the most common system and service manager on mainstream linux distributions. The bluez-alsa project now includes systemd service unit files for the bluealsa daemon and the bluealsa-aplay utility.

There are many different scenarios in which BlueALSA may be used, and the flexibility of systemd's configuration files means that there are equally many ways that the BlueALSA service units can be configured. The unit files provided by the project are intended to give a flexible and secure basis that can be used out-of-the box in the most common scenarios but can also be easily customized for any specialized use-case.

Installation

The BlueALSA systemd unit files are not installed by default, they must be explicitly enabled when configuring the build by including the configure option --enable-systemd. See Installation from source for more information on build and install procedure for BlueALSA.

There are also some configure options that can modify the unit files, setting the command-line arguments and setting the user id under which each service should be started. By default both services are run as user root. bluealsa is started with bluealsa -p a2dp-source -p a2dp-sink and bluealsa-aplay is started with no arguments. See the respective manual pages for full details of all available command-line arguments bluealsa manual page, bluealsa-aplay manual page.

It is generally considered best practice not to run services as root unless absolutely necessary. Neither of the BlueALSA services need root privileges, so long as the accounts they use have the required group memberships, and for bluealsa D-Bus permission is correctly granted to the chosen user. For maximum security, the chosen user accounts should be "system" accounts, which means each should:

  • have its own group
  • have no home directory
  • have no shell
  • have logins disabled

Distributions vary in the way that user and group accounts are created, so you should consult you distribution's documentation for instructions. As an example, on Debian and derivatives you can create suitable accounts called bluealsa and bluealsa-aplay with

sudo adduser --system --group --no-create-home bluealsa
sudo adduser --system --group --no-create-home bluealsa-aplay
sudo adduser bluealsa-aplay audio

If you are using bluez 5.50 or older you will also need to add the bluealsa user to the bluetooth group:

sudo adduser bluealsa bluetooth

(Note that adduser is a Debian utility; other distributions will likely have alternative utilities, each with its own command-line syntax).

For more details on the BlueALSA configure options for systemd, see the "Installation Options" section of the Installation from source wiki page.

Once the installation is complete, systemd needs to be informed of the new services by running (as root)

systemctl daemon-reload

Earlier BlueALSA releases

If using BlueALSA v3.1.0 or earlier, systemd unit files are not included in the sources. The file templates can be obtained from the latest sources: bluealsa service file template and bluealsa-aplay service file template. It is necessary to modify the User= and ExecStart= directives in both templates then save them without the .in suffix to create usable systemd service files. For example, the bluealsa.service file may be edited to contain the lines

User=root
ExecStart=/usr/bin/bluealsa -p a2dp-source -p a2dp-sink

Security Sandbox

The BlueALSA service unit files include comprehensive security sandbox directives aimed at providing the most complete lock-down possible and thereby reducing the security risk exposure to an absolute minimum.

A default install, with user root for both services, results in the following security analysis report for bluealsa.service from systemd-analyze security bluealsa.service (showing only those items identified as security risks):

✗ PrivateNetwork=                    Service has access to the host's network                            0.5
✗ User=/DynamicUser=                 Service runs as root user                                           0.4
✗ RestrictAddressFamilies=~…         Service may allocate exotic sockets                                 0.3
✗ DeviceAllow=                       Service has a device ACL with some special devices                  0.1
✗ RootDirectory=/RootImage=          Service runs within the host's root directory                       0.1
✗ RestrictAddressFamilies=~AF_UNIX   Service may allocate local sockets                                  0.1
✗ ProcSubset=                        Service has full access to non-process /proc files (/proc subset=)  0.1

Overall exposure level for bluealsa.service: 1.2 OK 🙂

The exposure level can be further reduced by running the service as a non-root user as described in Installation above. This removes the User=/DynamicUser= score resulting in an overall rating of:

Overall exposure level for bluealsa.service: 0.8 SAFE 😀

The remaining directives cannot be further tightened because they are required for the function of the bluealsa service. Each of the exposure report scoring items is discussed here:

  • PrivateNetwork=
    Permits creation of Unix Domain sockets, which is required for HFP/HSP RFCOMM function. If a system does not require SCO support, then PrivateNetwork can be enabled. Note that the client PCM control sockets are actually created by D-Bus, so bluealsa does not need this permission for those; however see also RestrictAddressFamilies=~AF_UNIX below.
  • RestrictAddressFamilies=~…
    The "exotic" sockets referenced here are in fact Bluetooth sockets which are required for access to the HCI through which all bluetooth data flows.
  • DeviceAllow=
    This is actually a consequence of the ProtectClock=true directive, and is therefore not avoidable.
  • RootDirectory=/RootImage=
    The purpose of this directive is to run the service in a chroot() jail. Since that would require a full set of the dependency libraries within the chroot, it is not possible for the BlueALSA installer to set this up in a generic way. In general, use of User= in combination with the other directives here gives equivalent protection.
  • RestrictAddressFamilies=~AF_UNIX
    Use of Unix domain sockets is required so that clients can connect to the bluealsa service.
  • ProcSubset=
    Although bluealsa does not need access to other processes' data, it does require access to certain kernel APIs, which would be denied by setting this directive.

systemd-analyze security bluealsa-aplay.service produces a similar report:

✗ PrivateNetwork=                     Service has access to the host's network                            0.5
✗ User=/DynamicUser=                  Service runs as root user                                           0.4
✗ DeviceAllow=                        Service has a device ACL with some special devices                  0.1
✗ RootDirectory=/RootImage=           Service runs within the host's root directory                       0.1
✗ RestrictAddressFamilies=~AF_UNIX    Service may allocate local sockets                                  0.1
✗ ProcSubset=                         Service has full access to non-process /proc files (/proc subset=)  0.1
✗ PrivateDevices=                     Service potentially has access to hardware devices                  0.2

Overall exposure level for bluealsa-aplay.service: 1.2 OK 🙂

... and again use of a non-root user gives the same improvement:

Overall exposure level for bluealsa-aplay.service: 0.8 SAFE 😀

The only difference from the bluealsa report is that bluealsa-aplay does not require bluetooth sockets, but that is balanced by the need for access to hardware sound devices (PrivateDevices=).

Usage

Please consult your distribution's documentation or the systemd documentation if you need help with using systemd services.

The service unit files can be used to start bluealsa and bluealsa-aplay when the bluetooth subsystem starts (typically at boot) by "enabling" them:

sudo systemctl enable bluealsa.service
sudo systemctl enable bluealsa-aplay.service

Note that if using bluealsa-aplay with HFP or HSP (bluealsa-aplay --profile-sco) then it should not be started at boot on a gateway host (HFP-AG or HSP-AG); this is because it will cause bluealsa to aquire the SCO transport as soon as a device connects, even though there may be no audio stream available in either direction at that time. This will waste bandwidth and battery power on the remote device. It is OK to start bluealsa-aplay at boot on a hands-free/headset host (HFP-HF or HSP-HS) because in that role bluealsa will not immediately acquire the transport.

It is also possible to start and stop either service manually, whether "enabled" or not, for example:

sudo systemctl start bluealsa.service
sudo systemctl stop bluealsa.service

Debugging and Troubleshooting

When BlueALSA is built with the option --enable-debug the bluealsa daemon and bluealsa-aplay application both produce large amounts of debug output. This output is sent to stderr, which by default systemd redirects to its journal file. This makes such builds less suitable for use with systemd, especially on embedded and other small systems with limited file space. It is therefore recommended not to run debug builds using systemd.

If you do need to run debug builds from systemd for any reason, then the logs will be visible using the systemd journalctl utility. For example:

sudo journalctl -xeu bluealsa.service

sudo journalctl -xeu bluealsa-aplay.service