MPRIS on headless systems

D-Bus offers two types of communication buses, the system and the session bus. By default and in most setups, MPRIS is expected to run on the session bus (for example, playerctl requires that). However, in headless contexts, the session bus is usually not available.

In this case, you basically have two options:

Option 1: Launch with dbus-launch

By creating a wrapper script and using dbus-launch, spotifyd can be run with its own bus. This could look like the following

./spotify_wrapper.sh:

#!/bin/bash

echo "$DBUS_SESSION_BUS_ADDRESS" > /tmp/spotifyd_bus
echo "To use spotifyd's session bus, run 'export DBUS_SESSION_BUS_ADDRESS=$(cat /tmp/spotifyd_bus)'"
spotifyd --no-daemon --use-mpris

Then, execute this script using dbus-launch ./spotify_wrapper.sh and follow the instructions in the output.

Option 2: Using the system bus

Instead of creating a new session bus, we can instead make use of the always existing system bus. To instruct spotifyd to use the system instead of the session bus, set the --dbus-type system cli flag / dbus_type = "system" config value.

By default, requesting names on the system bus requires special priveleges, which spotifyd doesn't have. So, unless being run as root, this will fail. To allow a non-root user to request the spotifyd name, we need to create the following file (replacing your user by something sensible):

/usr/share/dbus-1/system.d/spotifyd.conf:

<!DOCTYPE busconfig PUBLIC
          "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
          "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <!-- Only this user can own the spotifyd interfaces -->
  <policy user="your user">
    <allow own_prefix="rs.spotifyd"/>
    <allow own_prefix="org.mpris.MediaPlayer2.spotifyd"/>
  </policy>

  <!-- Allow this user, to invoke methods on these two interfaces -->
  <policy user="your user">
    <allow send_destination_prefix="rs.spotifyd"/>
    <allow send_destination_prefix="org.mpris.MediaPlayer2.spotifyd"/>
  </policy>
</busconfig>

Make sure to reload the D-Bus configuration with systemctl reload dbus.