Skip to content

Systemd integration

borine edited this page Oct 29, 2021 · 35 revisions

The examples in this article use the Debian systemd unit file style. The current BlueALSA sources (not yet in any releases) now include installable unit files that use the Redhat unit file style, as recommended by the systemd developers. This article will be updated to explain the use of the new included unit files in due course.

Using bluealsa with systemd

Systemd (https://www.freedesktop.org/wiki/Software/systemd/) is now the most common system and service manager on mainstream linux distributions. This article describes a method to manage bluealsa with systemd.

Service unit file

The bluealsa daemon should be managed as a service unit within systemd. It may be defined as type "simple" or type "dbus". The only difference is in the handling of consequent units by systemd (i.e. units that are set to start "After=bluealsa.service") - the choice does not affect the behaviour of bluealsa itself.

For "simple" type, any unit that is set to start after bluealsa will be started as soon as the bluealsa daemon has been started. For "dbus" type, those units will not be started until bluealsa has acquired the D-Bus bus name set by "Busname=". Since bluealsa is unable to perform any useful function until that name is acquired, we recommend using type "dbus".

There are many different scenarios in which bluealsa may be used, and the flexibility of systemd's configuration files means that there are equally may ways that the bluealsa service units can be configured. It is impossible to elaborate all possibilities, so instead we provide a fairly simple configuration that is reasonably secure and flexible enough to to support many common use cases.

Here is an example unit file to manage bluealsa with systemd. To use it, save it as:

/usr/local/lib/systemd/system/bluealsa.service

[Unit]
Description=Bluealsa daemon
Documentation=https://github.com/Arkq/bluez-alsa/
After=dbus-org.bluez.service
Requires=dbus-org.bluez.service

[Service]
Type=dbus
BusName=org.bluealsa
EnvironmentFile=-/etc/default/bluealsa
ExecStart=/usr/bin/bluealsa $OPTIONS
Restart=on-failure
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
RemoveIPC=true
RestrictAddressFamilies=AF_UNIX AF_BLUETOOTH
; Also non-privileged can user be used
; this example assumes a user and group called 'bluealsa' exist
;User=bluealsa
;Group=bluealsa
;NoNewPrivileges=true

[Install]
WantedBy=bluetooth.target

If you wish to pass some command-line options to bluealsa when it starts, define the environment variable OPTIONS in the file:

/etc/default/bluealsa

For example:

OPTIONS="-p a2dp-source -p a2dp-sink"

Inform systemd of the new service by:

$ sudo systemctl daemon-reload

Notes:

  1. The use of "dbus-org.bluez.service" and "bluetooth.target" in the systemd unit file above should work in the majority of cases; but note that a particular distribution may choose to use different names, and in that case you would have to consult the documentation for your distribution.

  2. If you want the bluealsa daemon to run under a dedicated account (i.e. non-root), you should also modify dbus configuration. Modify the file
    /etc/dbus-1/system-local.conf to include a policy for the dedicated account (or create it if it does not exist). For example if the file does not exist create it with this content:

<!DOCTYPE busconfig PUBLIC
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">

<busconfig>

    <policy user="bluealsa">
        <allow own_prefix="org.bluealsa"/>
        <allow send_destination="org.bluealsa"/>
        <allow send_destination="org.bluez"/>
    </policy>

</busconfig>

If the file already exists, just add the above <policy> ... </policy> block into the existing <busconfig> ... </busconfig> section. This method is preferable to editing the file /etc/dbus-1/system.d/bluealsa.conf because changes to that file will be lost if you later re-install bluealsa.

Starting (and stopping) bluealsa

start automatically with the rest of the bluetooth stack

Bluealsa is designed to use minimal system resources when idle, and so on most systems it is acceptable (and advisable) to start it at the same time as the bluetooth service and leave it running. The above example service unit file can be set to start in this way with:

$ sudo systemctl enable bluealsa.service

To cancel this, so that bluealsa does not start automatically on subsequent boots, use:

$ sudo systemctl disable bluealsa.service

start manually from the command line

Bluealsa can be started, and stopped, independently of the bluetooth service using the commands:

$ sudo systemctl start bluealsa.service

$ sudo systemctl stop bluealsa.service

This technique works whether or not you have chosen to enable the automatic start as described above.

start on demand by a D-Bus client

If bluealsa is only required when certain clients are running, instead of using the systemctl enable method above, D-Bus can be configured to start it automatically when a client requests it. This may be useful, for example, with audio management applications that attempt to monitor bluetooth devices; however, for clients such as aplay or other simple alsa applications, in this case no bluetooth audio devices will yet be connected, so the client request will fail. Therefore this method is only suitable in certain specialised cases. To enable this feature, create the following file:

/usr/share/dbus-1/system-services/org.bluealsa.service

[D-BUS Service]
Name=org.bluealsa
Exec=/bin/false
User=root
SystemdService=bluealsa.service

Notes:

  1. This method is only really suitable for use with applications that are not themselves managed by systemd. In all other cases it is preferable to use systemd dependencies to achieve the same result.
  2. Once started in this way, bluealsa will continue to run, as D-Bus does not stop it when the client terminates.

Running bluealsa-aplay as a systemd service

bluealsa-aplay can also be used as a systemd service. For example, create this systemd unit file:

/usr/local/lib/systemd/system/bluealsa-aplay.service

[Unit]
Description=Bluealsa audio player
Documentation=https://github.com/Arkq/bluez-alsa/
Wants=bluealsa.service

[Service]
Type=simple
;default to all devices - can be overridden in the EnvironmentFile
Environment="BT_ADDR=00:00:00:00:00:00"
EnvironmentFile=-/etc/default/bluealsa-aplay
ExecStart=/usr/bin/bluealsa-aplay $OPTIONS $BT_ADDR
Restart=on-failure
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
RemoveIPC=true
RestrictAddressFamilies=AF_UNIX
; Also non-privileged can user be used
; this example assumes a user called 'bluealsa-aplay' exists in the group 'audio'
;User=bluealsa-aplay
;Group=audio
;NoNewPrivileges=true

[Install]
WantedBy=bluetooth.target

If you wish to pass some command-line options to bluealsa-aplay when it starts, create the file:

/etc/default/bluealsa-aplay

In this file, define the environment variables OPTIONS to set non-default options and/or BT_ADDR to restrict the devices that will be accepted.

For example:

OPTIONS="--profile-sco --pcm=plughw:1,0"
BT_ADDR="01:02:03:04:05:06 A1:A2:A3:A4:A5:A6"

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.

If you 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