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.
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).
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 -a -G roon $USER
% 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.
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
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
- the starting
- 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/
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
.
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.
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! 🎶
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.
Indeed. I must have used
-a
or done something slightly different, because I'm still in the key sudoer group: