I have wanted to get remote sound sinks working ever since it saw it in action during a local Linux user group meeting. It was a bit beautiful in its simplicity – once you connected to the Wi-Fi the remote sink for the wireless speakers would magically appear, you select it as your sound output and you’re done. No cords, no passwords, no awkward pairing, and no noticeable delay.

With the help of a Raspberry Pi and a few spare moments during the holidays I was able to get everything up and running.

Overview

There are really two services that come together to make the process seamless. The first is Avahi, an mDNS/DNS-SD system which publishes the remote sound sink with a service record. The second is PulseAudio which runs a daemon listening on port 4713.

The PulseAudio client, configured with the ZeroConf module uses mDNS to search for service records for the sound server. You can search for these records manually on your network with the avahi-browse command.

avahi-browse -r _pulse-server._tcp

Once the client finds a remote sound server it will connect to the port specified in the service record, discover remote sinks and present them in the UI.

Server Setup

I already had a Raspberry Pi running the latest Raspbian so I will omit those directions for brevity.

First you’ll want to install and start Avahi.

# This is technically all you need.
apt install avahi-daemon

# For debugging you might also want the browsing tools.
apt install avahi-utils

# Raspbian automatically enables services when they're installed so this
# shouldn't be neccessary but just in case.
systemctl enable --now avahi-daemon

Then you’ll need to install PulseAudio and the required modules.

apt install pulseaudio pulseaudio-module-zeroconf

The PulseAudio package doesn’t include a service file for running it in system mode so we’ll have to provide one. Nothing particularly fancy is needed. We disallow runtime module loading on the recommendation of the developers for security purposes.

# /etc/systemd/system/pulseaudio.service

[Unit]
Description=PulseAudio System Daemon

[Service]
Type=simple
ExecStart=/usr/bin/pulseaudio --system --disallow-module-loading

[Install]
WantedBy=multi-user.target

The main configuration for PulseAudio when run as a system daemon is /etc/pulse/system.pa. The syntax for this file is odd for a freedesktop project but largely straightforward. Add the following lines to the end. You should change 192.168.0.0/16 to your local subnet.

# Make sinks available over the network.
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/16

# Publish sound sinks using Avahi.
load-module module-zeroconf-publish

Finally add port 4713 to the firewall and start the PulseAudio daemon.

firewall-cmd --permanent --add-port 4713/tcp
firewall-cmd --reload
systemctl enable --now pulseaudio

Client Setup

The name of the packages you’ll need to install will largely depend on how your distribution organizes things but other than PulseAudio itself I needed to install pulseaudio-zeroconf.

The main configuration file for daemons not running in system mode is /etc/pulse/default.pa. Add the following lines to the end and restart the daemon (logging out and back in will do the trick).

load-module module-zeroconf-discover

Then without any other prompting the sound sink should appear in your sound settings. Select it as the output and start listening to your music.

References