20130609

Making kvm/qemu/libvirt Play Nice with PulseAudio on a Headless Ubuntu 12.04 Server

I've been running over a dozen virtual machines on my headless server for almost two years now, and for all that time I've always missed being able to hear the audio from those machines. I would occasionally try to figure out how to make audio work over VNC, but never could find a solution on the Internet. Finally last week I decided to at least get part-way there by getting the audio to play on the server's speaker port. The first step was pretty easy – installing PulseAudio on the server:

sudo apt-get install pulseaudio

Now from what I could gather on the Internet, it seems like I needed to run PulseAudio in system mode, despite all the warnings that it should probably not be run that way. I figured that since I don't usually have any logged in users on the system, it would just be better to have it running all the time. In order to do that, I edited the /etc/default/pulseaudio file, and changed the following settings to:

PULSEAUDIO_SYSTEM_START=1
DISALLOW_MODULE_LOADING=1

Then I added my user and the libvirt-qemu user to the pulse-access group:

sudo adduser myuser pulse-access
sudo adduser libvirt-qemu pulse-access

You'll need to log out and back in again for the new group to be picked up on your shell. Finally, I started the PulseAudio service:

sudo service pulseaudio start

Now a quick test to make sure the sound subsystem was working:

paplay test-sound.wav

In my case, I could barely hear the sound playing, so I did a pactl list sinks to figure out which sink was being used, then issued
pactl set-sink-volume 1 100%
pactl set-sink-mute 1 0
to set the volume level of sink 1 to the maximum and unmute it. Now I could hear the sound just fine!

The next hurdle was to get the sound from the virtual machines to play through PulseAudio. It turns out there are quite a few obstacles to achieving that goal. First off, libvirt automatically disables audio if you are using a VNC client! It turns out to be fairly simple to fix that though, simply edit /etc/libvirt/qemu.conf and change the following setting to:

vnc_allow_host_audio = 1

After restarting the libvirt daemon using sudo service libvirt-bin restart I could see in the syslog file that libvirt/kvm was trying to use the PulseAudio subsytem, but apparmor was blocking access to several key files/directories. I never did find a working answer by Googling, but I worked out the following settings for the /etc/apparmor.d/abstractions/libvirt-qemu file. I changed /{dev,run}/shm r, to /{dev,run}/shm rw, then added /{dev,run}/shm/pulse* rw, right after that line. Finally I added /var/lib/libvirt/.pulse-cookie rwk, (note the trailing commas on those lines!) then told apparmor to reload the configuration:

sudo invoke-rc.d apparmor reload

I fired off a Windows XP x32 guest, and was able to hear sound, but it was very distorted and choppy. The solution to that was to change the sound hardware in the virtual machine's configuration file from <sound model='ac97'> to <sound model='es1370'>. After that, I was getting perfect sound from my virtual machine!

Now for a few caveats – it seems that changing any of the PulseAudio configuration or restarting the service while the virtual machine is running can cause problems like the sound no longer working, all the way to the virtual machine's OS hanging up trying to play sounds. So once you started your virtual machine, leave things alone! I have also been working on trying to forward the sound over the network to my workstation, but so far I am having mixed results with that. Hopefully I'll have another post soon describing how to make that work.

And here is the usual warning that goes with tweaking your system like this: These instructions worked for me, but your mileage may vary. Also, I won't be responsible if any of this causes your machine to stop working or catch on fire – but this stuff should be pretty straight-forward and not cause any serious issues that can't be reversed. Hopefully my adventure will help you to enjoy hearing from your virtual machines. If you have any questions or corrections, please feel free to post them in the comments.

1 comments:

Ivan Avery Frey said...

I too am trying to get sound from a Win7 guest.

Except I'm using Spice instead of VNC. Your post has given some ideas which I will look into.

BTW, there are paravirtualized drivers you can install for the windows guest when you use spice.

 
Template design by Amanda @ Blogger Buster