We run the Pulseaudio audio server in order to produce semi-reliable audio tunneling from office terminals to nullsleep and the office speakers.
Pulseaudio has two running modes: per-user and systemwide. Per-user is the default; systemwide is not officially unsupported, but it's classed as "You're probably doing it wrong." Basically, pulse can either start one daemon per user attempting to use audio, or one daemon for the entire system. Due to security reasons, system mode is usually wrong, but in our case, it's correct, as nullsleep is a multi-user setup and we need mpd to be able to access audio even if no user is logged in. Note that in our case, some of the security flaws, like allowing users to mess with others' audio streams, are actually features: anyone in the audio group can mute anyone else's audio if it's being annoying.
Pulseaudio is modular and supports dynamically adding sinks and sources for audio, and connecting and reconnecting them, changing volume, whatever. I'm not aware of any at the moment, but it would definitely be possible to write a fully-featured switchboard application which could easily rewire audio, run transformations, or generally do interesting things (an example: for someone streaming, make it so that they can hear sounds generated by applications in their headphones, and their own background music, but not the mic, while the stream application gets the application audio and the microphone, but not the background music).
In our CSC case, we use pulseaudio's network tunneling support to allow routing audio from any office terminal to nullsleep. Sometimes it's choppy, sometimes it isn't. We haven't figured out why, and it seems to occur/stop pseudo-randomly.
We need to ensure that only members of the audio group can access the speakers. This is done in two ways. The first is, for the UNIX domain sockets used by applications running on the audio server (currently nullsleep), we restrict them to members of the audio group. Easy!
For the network tunneling, however, we sadly (depending on your point of view) don't yet have a kerberized tunneling module for pulse, so we have to use a bit more jury-rigging. Pulse supports a few security mechanisms for IP tunneling, and we use a combination of two: a magic cookie, and IP address restriction.
The magic cookie is very simple in principle: when in use, a pulseaudio client must know the magic cookie known to the server, or else the connection is refused. In order to make this work for all office terminals, we keep two copies of the cookie: one at /users/audio/.pulse-cookie, accessible to users in the audio group, and one in /etc/pulse/cookie on the server. If a non-audio user starts up pulse, we have it configured to ignore its inability to read the cookie file, so they simply get normal audio on the machine (for headphones or something) without the ability to tunnel. The pulse server cannot use the /users copy because it doesn't have a Kerberos ticket, so we keep a separate copy locally. In the event that these become out of sync, one can be copied over to the other with little fanfare, or new ones can be generated. All that matters is that the files match.
Put pulse into system mode
Since system mode is not really supported, we need to do a bit of lifting to make it work. First, go to /usr/share/doc/pulseaudio/examples and you will find pulseaudio.default.example and pulseaudio.init.example. Copy the first to /etc/default/pulseaudio and the second to /etc/init.d/pulseaudio to ensure that we can configure it for startup. Then, in /etc/default/pulseaudio, change the flag
systemctl daemon-reload to make systemd aware of the new init script, and
systemctl enable pulseaudio to turn it on.
Configure the pulse server
Now head to /etc/pulse. First off, in client.conf, set autospawn = no. This will prevent individual instances of pulse spawning and sowing confusion. In daemon.conf, make sure the following are set:
daemonize = yes local-server-type = system system-instance = yes allow-module-loading = no
Finally, we need to configure the sinks and authorization. In system.pa, replace
load-module module-native-protocol-unix auth-anonymous=1 ### CSC tunneling load-module module-native-protocol-tcp auth-cookie=/etc/pulse/cookie auth-ip-acl=126.96.36.199/24
Client configuration is much easier. In /etc/pulse/default.pa, add the following somewhere:
load-module module-tunnel-sink server=$SERVER cookie=/users/audio/.pulse-cookie
$SERVER is the hostname of the server to connect to (e.g.
Use pavucontrol to connect sources to the tunnel sink (usually called pulse@nullsleep). Volume can be controlled locally, or by running pavucontrol via SSH tunnel on nullsleep
If you wish to debug pulseaudio on an office terminal, connect via ssh (so as not to spawn a default pulse instance by any application/desktop environment) and run pulseaudio -v to get extended output. Remember that you need to be in the audio group for pulse@nullsleep to show up. You can use pactl to query the state of the running daemon more precisely.
Pulseaudio was written by Lennart