Pulseaudio: Multi-User Setup

Hello and welcome to my blog. If you are finding this page, then you might be in a similar situation I found myself when I wanted to share audio with different apps if they were being used by different user accounts on your local *nix machine when using Pulse audio.

Credits to Eli Billauer and Dhole for the configuration directives I needed to make this possible.

The Problem

I have multiple user accounts on my system that run various apps, like my web browser, chat apps, email and more. I don't like everything running as myself and try to create a user account with just enough privileges to do what it needs to do.

Pulseaudio (herein "Pulse") runs as myself when my desktop environment starts. Apps that run normally need to connect to Pulse in some fashion in order to listen to the microphone or play audio on the speakers. When the apps all run as the logged in user, this works great. When the apps run as someone else, this doesn't work or is inconsistent in behaviour.

The Scenario

I have a user account chrome that is dedicated to the browser /usr/bin/google-chrome-stable. The browser will run as this account instead of myself and has just enough permissions to render on the screen and have basic access to some files on the filesystem (albeit, as the unprivileged account).

How do I make it possible to render sound and grant access to the mic when necessary to chrome?

The Solution

I use local UNIX sockets to allow applications to talk to Pulse and the system behaves. I also discovered you DO NOT need to modify the system configuration files in /etc.

There's a few configuration files and directives that are used and will be laid out here.

Server Configuration

As the user who runs Pulse (e.g. creates the server):

  • Create ~/.pulse if it doesn't exist already.
  • Create and populate ~/.pulse/default.pa with the content as described below in the block of configuration.
    • Please note: Pulse will look for local configurations before global configs and will stop looking for additional files once it finds a match. The configuration is not a layered configuration in that /etc is applied first, then local configuration overrides those values. If a local file is present, it should include all dependencies and global configuration files or else you could end up with a misconfigured setup.
  • Restart Pulse. Can use pulseaudio -k && pulseaudio -D. Please consult your distribution's documentation if the mechanism to start Pulse are different for you.
  • Personally, I had to chmod o-rwx /tmp/pulse-server (aka chmod 770 /tmp/pulse-server) to remove access to the socket outside of me and those part of the audio group I wanted apps to share if they were going to be using audio streams.

Pulse may run as yourself or a dedicated user just for dealing with sound.


.include /etc/pulse/default.pa

#load-module module-native-protocol-tcp auth-ip-acl=

### Load several protocols
load-module module-dbus-protocol
.ifexists module-esound-protocol-unix.so
load-module module-esound-protocol-unix
load-module module-native-protocol-unix auth-group=audio socket=/tmp/pulse-server

Client Configuration

As someone who will connect to Pulse and attempt to interact with the speakers and/or microphone, you'll need to include this configuration in every users' home directory under ~/.pulse/client.conf:

# Unix socket method
default-server = unix:/tmp/pulse-server
enable-memfd = yes

With this configuration, as each app started up, I noticed they were able to interact with audio without issues. I also restarted my Bluetooth daemon and was able to pass audio through my BT-headset!


Build xmrig on Linux

Hi all,

So, I am getting into the crypto-mining space a bit and I wanted to share a few things I've learned. This whole experience has been teaching me a lot as of late!
In this post, we'll be talking about xmrig what it is and how to compile it on Linux. I'm going to skip the wallet and other details as I wanted this post to be as context-specific and straight to the point as possible. Let's dive right in.

What is xmrig???

My take on this is xmrig is a swiss army knife of a mininig tool that can be used for many algorithms and various coins. I mostly found and used this to mine Monero (XMR), so we'll take that as an example. xmrig supports both CPU and GPU minining, but not all algorithms are CPU- or GPU- friendly. Some are specific to either, so be mindful of what you are doing when you are setting this up.
Let's dive into the build and running instructions and examples.

Building xmrig

I happen to be using debian-based systems to compile stuff. So you'll see some aptitude references in the installation scripts.
I also happen to have this handy script I used to install xmrig on various machines I have without having to think about much. Here's the script for reference: [1].

Script Notes

RUNNING AS ROOT: One thing to note about scripts that I write: I dislike things running as root. There were a lot of posts out there which said the problem was resolved once they ran the command as root. I don't know about you, but I really don't feel comfortable running some untrusted code as root in my system. I like to understand what its doing and give it just enough capabilities to do its job. So, I found out what those capability requirements were and baked them into this script.
As long as you use the resulting mine.sh script (or concepts from it), you should have a little more confidence that this does not require escalated privileges.

CUSTOMIZATION: Be sure to customize this with your preferences. For example, the mining pool of your choice, along with your wallet address. I noted these below in the script.

SUDO: No need to run the build script as root since it will sudo its way to privilege when necessary. Just make sure the user who runs the script has ability to run sudo commands.
However, you do need to run the resulting mine.sh script as root since it will set some options and drop privileges before executing your miner.

SETCAP: This is one of those low-level operations I discovered that normally requires root privileges. However, if there's one thing I have learned about Linux: If you have the right capabilities, you don't require root for anything (except to grant said permission, even then, you can dedicate a user to just that action). If you know what you are doing, you can avoid the root user for just about anything. One of the greatest strengths of Linux I love so much. I think this is why people just flatly said "just run it as root" and left it at that. With this capability set on the binary, it tells the system that it's okay for this particular process to perform this action without escalated privileges.


It should be as simple as executing the script. However, if months or years later you are coming across this blog post and the version has since changed, I left an easy add to that via an environment variable. So you can use:

xmrig_version=6.12.0 ./xmrig-build-all.sh

In order to compile this.
After the script executes and the code is built, I install the results to /usr/local/share/xmrig/xmrig-$xmrig_version and name the file accordingly. If you want CUDA support, run the script with that variable set to something non-empty as such:

WITH_CUDA=1 xmrig_version=6.12.0 ./xmrig-build-all.sh


Donations are greatly appreciated if you found this to be helpful!

  • ETH: 0xBfF52D9A244A1C333573f903737ec5eDb5a99150
  • DOGE: D89MZHmmFewdyksCs8EnXwj8XFn7AXrNsj
  • XMR: 49NE1L9WVJLcg7susCGSTAcbT5Fi8Ukq1JthDSjWkLdM6VrnvtZEdm7Vh36gFmdfR2hqKQ1pUKXT71BY9rKsUW3GJUL3Cbr
  • RVN: RMvGF8qpY3XjrGMuzfAMkwveehmqgZrhcF
I plan on posting several new pages about what is crypto and getting into these miners as I complete my research.
Thanks for taking the time to read through this!

[1]: xmrig-build.sh

#!/bin/bash -e

# This is the script we will be using to mine later.
# Stored as a string for us to write to a script file later in this installation script.

# While root, relax the memory limits and set permissions on the MSR stuff
#  for the CPU since it seems to revert at each reboot.
test "$UID" -eq 0 && {
  ulimit -l 10240
  modprobe msr
  chgrp msr /dev/cpu/*/msr
  chmod g+rw /dev/cpu/*/msr

test "$UID" -eq `id -u $RUNAS_USER` || {
  echo "Dropping privileges..."
  exec sudo -H -u$RUNAS_USER -g$RUNAS_GROUP \
    MINER_HOME=${MINER_HOME} "$0" $@

test -z "$MINER_DEBUG" || {
  set -x

MINER_NAME=${MINER_NAME:-`hostname -s`}


exec xmrig --threads=`nproc` \
  -o "${MINER_POOL}" \
  -u "${MINER_WALLET}" \
  -p "${MINER_NAME}" \
  -k --tls --coin monero $@

# Setup some variables and build the xmrig software.


# If you use RHEL/Arch/Gentoo/Other, replace this with your pkg-mgr and names of the respective packages.
sudo apt-get install -y git build-essential cmake libuv1-dev libssl-dev libhwloc-dev msr-tools

# https://stackoverflow.com/questions/18661976/reading-dev-cpu-msr-from-userspace-operation-not-permitted
# Found out why I get the MSR error. This is the fix.
modprobe msr || true
grep msr /etc/group || sudo groupadd --system msr
sudo chmod g+rw /dev/cpu/*/msr
sudo chgrp msr /dev/cpu/*/msr

test -d $xmrig || git clone --depth 1 --branch v$xmrig_version git@github.com:xmrig/xmrig $xmrig
test -d $xmrig/build || mkdir $xmrig/build

test -z "$WITH_CUDA" || {
  test -d $cuda  || git clone --depth 1 --branch v$cuda_version git@github.com:xmrig/xmrig-cuda $cuda
  test -d $cuda/build  || mkdir $cuda/build

test -d /usr/local/share/xmrig || sudo install -d -oroot -gstaff -m2755 /usr/local/share/xmrig

  cd $xmrig/build
  cmake ..
  make -j`nproc`
  sudo install -v -oroot -gstaff ./xmrig /usr/local/share/xmrig/xmrig-$xmrig_version
  # This sets a capability on the binary itself in order to have raw IO operations against the CPU for MSR to work.
  sudo setcap cap_sys_rawio=ep /usr/local/share/xmrig/xmrig-$xmrig_version

test -z "$WITH_CUDA" || {(
  cd $cuda/build
  # If you have issues with cuda, add the following to specify it directly:
  #  -DCUDA_LIB=/usr/local/cuda/targets/x86_64-linux/lib/stubs/libcuda.so -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda
  if [ `gcc -dumpversion` -ge 10 ]; then
    # xmrig-cuda does not appear to support gcc-10 just yet. If this changes,
    # remove this if(){} block and the subsequent variable from `cmake'.
  # Change CUDA_ARCH to what works for your installation: https://developer.nvidia.com/cuda-gpus
  cmake .. -DCUDA_ARCH=61 $CMAKE_OPTS
  make -j`nproc`
  sudo install -v -oroot -gstaff ./libxmrig-cuda.so /usr/local/share/xmrig/
  slaves="--slave /usr/lib/libxmrig-cuda.so libxmrig-cuda.so /usr/local/share/xmrig/libxmrig-cuda.so"

# Make the software live and available to the rest of the system thru update-alternatives.
sudo update-alternatives --install /usr/local/bin/xmrig xmrig /usr/local/share/xmrig/xmrig-$xmrig_version 100 $slaves

# Enable hugepage support.
sudo sysctl -w vm.nr_hugepages=1280

# setup the non-privileged account that will enable us to mine!
getent group crypto >/dev/null || groupadd --system crypto
group_gid=`getent group crypto | cut -d: -f3`
id xmr || sudo useradd --gid=$group_gid --shell /usr/sbin/nologin --system --home /var/lib/crypto/xmr -m -G msr xmr
test -d ~xmr/bin || sudo install -d -oxmr -gapps ~xmr/bin
test -f ~xmr/bin/mine.sh || echo "$XMR_MINE_SCRIPT" | sudo install -oxmr -gapps /dev/stdin ~xmr/bin/mine.sh

echo "You can now run sudo /var/lib/crypto/xmr/bin/mine.sh"
echo "Complete!"