Skip to content

Instantly share code, notes, and snippets.

@skierpage
Last active January 22, 2024 18:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skierpage/986961438443eb78745a54eadfc9a1b8 to your computer and use it in GitHub Desktop.
Save skierpage/986961438443eb78745a54eadfc9a1b8 to your computer and use it in GitHub Desktop.
Installing Roon Server on Fedora Linux _not_ as root

I just installed Roon Server on my laptop running Fedora 37 Workstation as a separate roon user instead of the security insanity :crazy_face: of the default Linux which installs and runs as the root user. I did this before, it went a little smoother this time. Here are my notes, they extend Roon's own Installing Roon on Linux documentation.

Disclaimer 1! If these commands don't make sense ("do I enter the '%'?" "what is sudo?"), then don't follow this, and take the risk by running the Easy install. Disclaimer 2 This is an edited version of what I did omitting all the false starts and failed commands. I didn't QA these by uninstalling and reverting everything and starting again from scratch following my own instructions.

Dependencies

I had them all installed already, but this should work in Fedora:

% sudo dnf install ffmpeg alsa-lib cifs-utils
% dnf --cacheonly --installed info glibc

(the latter reports version the version of glibc installed is at version 2.36, high enough).

User roon

Create separate user "roon" who will own the files and run Roon Server (but can't read or write my files).

% sudo useradd roon

Create a password for this user. (This might not be necessary, I'm inexpert about running commands as another user with sudo --user=roon do-something.)

% sudo passwd roon
   (enter a password)

To make it easier to debug and view files, I added myself to the roon group that useradd creates along with the user roon.

% sudo usermod -G roon $USER

Get the code

% cd /tmp
% wget https://download.roonlabs.net/builds/RoonServer_linuxx64.tar.bz2

Unpack the code (It's all under a RoonServer/ directory) as user roon

% su -l roon
% cd /tmp
% tar --bzip2 -xvf RoonServer_linuxx64.tar.bz2
% exit

install page says the Easy Installer installs to /opt/RoonServer, so move the files there. (I already had a /opt directory).

% sudo mv -i /tmp/RoonServer /opt/.

Set up the same /var/roon directory for the database and logs as the Easy Installer uses, make it owned by the roon user and group roon.

% sudo mkdir /var/roon
% sudo chown roon:roon /var/roon

Run the check script (I don't think you have to run this as the roon user).

% /opt/RoonServer/check.sh
        reports SUCCESS

At this point I ran the start script just to see if it starts.

% ROON_DATAROOT=/var/roon ./start.sh
% less /var/roon/RoonServer/Logs/RoonServer_log.txt
   (look for errors)

I think I ran kill PID to stop this temporary Roon Server test.

Setting up the firewalld rules for Roon Server

Fedora Workstation ships with firewalld and iptables. I chose to add a service to firewalld even though its user interface is confusing. I reused my old firewall settings for a Roon Server service from this thread, they're in this gist . Save that somewhere as roon-server.xml, then tell firewalld about it with

% sudo firewall-cmd --permanent --new-service-from-file=/path/to/roon-server.xml

This copies the service to /etc/firewalld/services/ minus comments. I don't think it actually enables it, but the GUI firewall configuration tool is hella confusing. I struggled with the firewall rule not working but then I couldn't re-run because it was already present. So to be safe, try to unload (disable?) it with

% sudo firewall-cmd --remove-service=roon-server

Starting RoonServer as a systemd service

I edited the lines in the easy install's roonserver-installer-linuxx64.sh script that create "SERVICE_FILE", to create the following roonserver.service file:

[Unit]
Description=RoonServer
After=network-online.target

[Service]
Type=simple
# I installed Roon so that it runs with user permissions instead of as root;
# this required some SELinux fussing around,
# and automounting network media drives probably won't work.
User=roon
Environment=SYSTEMD_LOG_LEVEL=debug
Environment=ROON_DATAROOT=/var/roon
Environment=ROON_ID_DIR=/var/roon
# Enable/disable roon-server firewall rules before/after ('+' runs the commands as root).
ExecStartPre=+/usr/bin/firewall-cmd --add-service=roon-server
ExecStart=/opt/RoonServer/start.sh
ExecStopPost=+/usr/bin/firewall-cmd --remove-service=roon-server
Restart=on-abort

[Install]
### Manual start. Or could run upon login as Roon user?
### WantedBy=multi-user.target

The key changes are:

  • User=roon instead of root
  • before starting Roon Server load the firewalld rules for roon-server (see earlier)
    • the starting + runs the command as root
  • when Roon Server stops, unload the firewalld rules so Roon Server's mess of open ports are closed again
  • I disable automatic start ("WantedBy")

Copy this to where systemd can find it

% sudo cp -pi roonserver.service /etc/systemd/system/

Making SELinux happy

The first time I tried to run this systemd service, it failed. I got a warning about avc denial or something, was able to open the "SELinux Alert Browser" GUI tool, which told me about a problem with start.sh trying to run start.sh. Huh? But it also told me what to do to fix it:

% sudo /sbin/restorecon -v /opt/RoonServer/start.sh

restorecon is a SELinux command. Fedora Workstation runs Security Enhanced Linux, which enforces certain limitations on what programs can do. Like suggestions to "just disable the firewall," any program that suggests disabling SELinux is being lazy.

You can also run tail -f /var/log/audit/audit.log & to see if SELinux complains, though it's hard to tell in its output.

Now I can start Roon Server with the usual

% systemctl start roonserver

systemd command (Fedora KDE puts up a Authentication Required dialog prompting me to enter my password for this, otherwise prepend the command with sudo). I can also check its status with systemctl status roonserver, and stop it with systemctl stop roonserver.

Giving the roon user access to my music

As user roon, I created a symlink to my music directory in roon's home directory:

% su -l roon
% ln -s /path/to/my/Music/folder myMusic
% ls -R ~/myMusic
    (should list all your music)

If user roon can't see all your music, you need to change permissions or groups so that it can. In my case my music folder is on a Windows NTFS partition, and the listing command failed. I wound up changing my Windows NTFS partition's mount line in /etc/fstab so that the drive is mounted with the group ID of the roon user. That means Roon Server can read but not write to my music folder.

Setting up Roon Server

With the Roon Server systemd service running, Roon Control running on my Android phone could find Roon Server over Wi-fi! (It remembered my old Roon server and prompted me to unauthorize/remove? it, which I did.) I pointed it to /home/roon/myMusic, songs started to appear in the UI, and I could play music to my Roon endpoints! 🎶

Other issues

I have a really simple setup with no plug-ins, API use, subnets, ARC, network attached storage, music on removable flash drives, etc. These could probably require changes to the firewalld rules, and/or writing udev rules and helper scripts, and/or changing permissions so the roon user can access other drives, and/or maybe further SELinux permissions adjustments.

But it's working for me, and no matter what bugs and exploits are found in Roon's code, I've limited the damage they can do by running as a separate user instead of as root.

I hope this helps. Sorry it's so long. I saved it as a gist on GitHub. Corrections and comments welcome.

@roblem
Copy link

roblem commented Jan 22, 2024

A word of caution:

sudo usermod -G roon $USER

will redefine your group membership to be roon only, which is a bad thing if your account is a sudoer (in wheels group) according to this reddit thread and in man. To avoid this use

sudo usermod -a -G roon $USER

to append membership to roon to the users groups.

To fix a borked system (with no sudo users), boot from live install media, mount the hardrive where you just lost sudo, and edit /etc/group to add the user to the wheel group.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment