-
Notifications
You must be signed in to change notification settings - Fork 189
Systemd integration
Important
This document refers to BlueALSA components by the names used in the latest sources. For release v4.3.1 or earlier please note that the bluealsad
daemon was called bluealsa
Systemd (systemd) is now the most common system and service manager on mainstream linux distributions. The bluez-alsa project includes systemd service unit files for the bluealsad
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.
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
. bluealsad
is started with bluealsad -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 bluealsad 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 bluealsad
D-Bus permission is correctly granted to the chosen acount. For maximum security, the chosen 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 your 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
If using BlueALSA v3.1.0 or earlier, systemd unit files are not included in the sources. Suitable file templates can be obtained from the v4.3.1 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 -S -p a2dp-source -p a2dp-sink
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 the bluealsad
daemon, 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
✗ PrivateUsers= Service has access to other users 0.2
✗ AmbientCapabilities= Service process receives ambient capabilities 0.1
✗ CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW) Service has elevated networking privileges 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.6 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: 1.2 OK 🙂
The directives PrivateUsers=false
, AmbientCapabilities=CAP_NET_RAW
, and CapabilityBoundingSet=CAP_NET_RAW
are required only to permit the bluealsa
daemon to modify SCO routing for Broadcom bluetooth adapters. If your system does not use Broadcom adapters, or if the system has its own means of setting the SCO routing, then these directives can be tightened. Change them to:
CapabilityBoundingSet=
AmbientCapabilities=
PrivateUsers=true
and the overall exposure level is further reduced:
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 bluealsad
daemon. 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, sobluealsad
does not need this permission for those; however see alsoRestrictAddressFamilies=~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 theProtectClock=true
directive, and is therefore not avoidable. - RootDirectory=/RootImage=
The purpose of this directive is to run the service in achroot()
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 ofUser=
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 thebluealsad
daemon. - ProcSubset=
Althoughbluealsad
does not need access to other processes' data, it does require access to certain kernel APIs, which would be denied by setting this directive.
BlueALSA release 4.2.0 and later includes the ability to run the bluealsad
daemon with real-time capabilities, and this is recommended when using the SCO profiles. See the bluealsa manual page for more information. This option requires some relaxing of the sandbox restrictions, which by default prevent the use of real-time priority. Note that misuse of this capability can cause a system-wide denial of service, and so should only be enabled for those services which genuinely require it and can be trusted. The additional service directives required are:
AmbientCapabilities=CAP_SYS_NICE
CapabilityBoundingSet=CAP_SYS_NICE
RestrictRealtime=false
SystemCallFilter=@resources
See the Usage section below for advice on editing the systemd configuration.
This naturally results in an increased security exposure risk:
✗ CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE) Service has privileges to change resource use parameters 0.1
✗ RestrictRealtime= Service may acquire realtime scheduling 0.1
✗ SystemCallFilter=~@resources System call allow list defined for service, and @resources is included (e.g. ioprio_set is allowed) 0.2
→ Overall exposure level for bluealsa.service: 1.9 OK 🙂
A default install, with user root
for the bluealsa-aplay
service, produces the following report from systemd-analyze security bluealsa-aplay.service
:
✗ 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=
).
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 bluealsad
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 bluealsad
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
If it becomes necessary to modify a systemd service unit after installation, it is best not to edit the original unit file. This is because such changes will be lost if BlueALSA is later re-installed or upgraded. Instead, the systemctl edit
utility can be used.
To make small changes, for example to the bluealsa service file, create a drop-in override by using:
sudo systemctl edit bluealsa.service
In this file, just place the directives you wish to override, including the appropriate group header (e.g. [Service]
etc). Note that although most directives allow only one value and are completely replaced by the override, some others permit multiple instances and so the override value is used in addition to the existing value.
A notable example of the multiple instance type is ExecStart
. To completely replace a multiple instance directive it is necessary to first clear it by specifying an empty value. So, for example to enable the aptX codec, the override file should be:
[Service]
ExecStart=
ExecStart=/usr/bin/bluealsad -S -p a2dp-source -p a2dp-sink -c aptx
If you wish to make many changes, the whole file can be replaced with:
sudo systemctl edit --full bluealsa.service
This creates a complete copy of the installed file. The copy "hides" the installed file so that the copy is not overwritten if BlueALSA is re-installed or upgraded.
To undo the overrides and restore the original installed file, use:
sudo systemctl revert bluealsa.service
Drop-in override changes take effect the next time the service is started. So to apply the changes immediately:
sudo systemctl restart bluealsa.service
See the systemctl
manual page for more information.
When BlueALSA is built with the option --enable-debug
the bluealsad
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