Describe the bug
I can't get the snapserver to run on my laptop or vm (Ubuntu 20.04 desktop and server). For some reason I got Permission denied error on piping /dev/urandom or any wav file into the default pipe /tmp/snapfifo even on minimal setup described below.
But running snapserver on a Raspberry Pi works just fine.
Steps to Reproduce
Setup server:
sudo dpkg -i snapserver_0.22.0-1_amd64.debsudo service snapserver startSetup client:
sudo dpkg -i snapclient*_armhf.deb/etc/default/snapclient with SNAPCLIENT_OPTS="--host laptop.local", and restart with sudo service snapclient restartSnapserver log on laptop (sudo journalctl -xu snapserver -f) shows that client connected successfully
Testing:
# on server
sudo su - # to be sure I'm redirecting as root
cat /dev/urandom > /tmp/snapfifo # this or,
cat some_audio.wav > /tmp/snapfifo
Both gives:
-bash: /tmp/snapfifo: Permission denied
Output of ls -lha /tmp/snapfifo:
prw-rw-rw- 1 snapserver snapserver 0 Dez 6 11:43 /tmp/snapfifo
Environment details
Possible Relevant Log Entries
There's an Exception: end of file the first time snapserver is started:
Dec 6 13:21:23 laptop snapserver[150929]: Adding source: pipe:///tmp/snapfifo?name=default
Dec 6 13:21:23 laptop snapserver[150929]: Settings file: "/var/lib/snapserver/server.json"
Dec 6 13:21:23 laptop snapserver[150929]: Adding service 'Snapcast'
Dec 6 13:21:23 laptop snapserver[150929]: PcmStream: default, sampleFormat: 48000:16:2
Dec 6 13:21:23 laptop snapserver[150929]: Stream: default, metadata={
Dec 6 13:21:23 laptop snapserver[150929]: "STREAM": "default"
Dec 6 13:21:23 laptop snapserver[150929]: }
Dec 6 13:21:23 laptop snapserver[150929]: onMetaChanged (default)
Dec 6 13:21:23 laptop snapserver[150929]: PipeStream mode: create
Dec 6 13:21:23 laptop snapserver[150929]: Stream: {"fragment":"","host":"","path":"/tmp/snapfifo","query":{"chunk_ms":"20","codec":"flac","name":"default","sampleformat":"48000:16:2"},"raw":"pipe:////tmp/snapfifo?chunk_ms=20&codec=flac&name=default&sampleformat=48000:16:2","scheme":"pipe"}
Dec 6 13:21:23 laptop snapserver[150929]: Exception: end of file
Dec 6 13:21:23 laptop snapserver[150929]: Creating TCP acceptor for address: 0.0.0.0, port: 1705
Dec 6 13:21:23 laptop snapserver[150929]: Creating HTTP acceptor for address: 0.0.0.0, port: 1780
Dec 6 13:21:23 laptop snapserver[150929]: Creating stream acceptor for address: 0.0.0.0, port: 1704
Dec 6 13:21:23 laptop snapserver[150929]: number of threads: 4, hw threads: 4
Any clue? Did I miss anything on the setup?
I would belive you don't have write permission on the /tmp/snapfifo for the user you are trying to start snapserver as
Are you starting the snapserver as correct user?
Try changing the permissions on /tmp/snapfifo
I would belive you don't have write permission on the /tmp/snapfifo for the user you are trying to start snapserver as
Are you starting the snapserver as correct user?
Try changing the permissions on /tmp/snapfifo
Interesting, changing owner of the named pipe into my username works..
As you can see on the first post, the permissions for the /tmp/snapfifo are rw-rw-rw- and it's owned by snapserver user. Process also runs as snapserver user. Despite that, even root can't pipe there. I tried chmod 777, still permission denied.
This happens on Ubuntu (20.04 Server and Desktop). On Raspberry OS it works fine.
I'm planning to run a music player server (Mopidy or Volumio) on the same VM running snapserver. I am assuming this is a common use case for snapserver, how would you think the cleaner way to make this work? Hacky hack solution would be to chmod the /tmp/snapfifo persistently to music's player username.
I can reproduce it on my recently updated Mint 20 Laptop, and googled for you... :wink:
It's a security feature for fifo files in sticky directories (such as /tmp/) as described here and in the kernel commit message
You can check if fifo protection is activated with
sudo sysctl -n fs.protected_fifos
and disable/enable it with
sudo sysctl fs.protected_fifos=0/1
I recommend to use a different (non-sticky) directory for the fifo file.
So this is +1 for issue #486
It really would be better to finally move the default pipe location to /run. It's absolutely where it belongs.
@badaix that works, thanks! Learned something new today :)
For future reader: run following commands to make this setting permanent
echo "fs.protected_fifos = 0" | sudo tee /etc/sysctl.d/snapcast-unprotect-fifo.conf
and reload sysctl with sudo service procps force-reload or reboot. sudo sysctl fs.protected_fifos should now output 0
@ariandyy reopened because it's not really solved, but the problem is identified
@djmattyg007 as described by @tgurr in #486 /run seems to be the appropriate location, but needs some more systemd configuration. I'm afraid that if I change the default from /tmp to /run I will receive the next shitstorm from non-systemd users. Providing packages is not in the focus of this project (debian packages are built automatically, because I'm using debian based distros and thus it's convenient for me to have them).
Unfortunately there are many user reacting with thumbs up to #486, but no one is providing a patch that will solve the issue in a reliable way.
For the moment I will just reopen the issue, maybe it will help other users or someone even takes it on and provides a patch.
Usage of /run shouldn't have any dependency on systemd. If someone's using such an old distribution that they don't have /run, it's trivial for them to change it to /var/run (which has been around for much longer).
If you are using systemd (which is likely the case for most people), it would be much easier if the default configuration just worked rather than requiring changes to sysctls that lessen the overall safety of the system.
The Arch package comes with a systemd-tmpfiles config file that automatically creates the folder /run/snapserver when snapserver.service is created:
https://aur.archlinux.org/cgit/aur.git/tree/snapcast.tmpfiles?h=snapcast
Other init systems will likely have ways of handling this automatically, or if nothing else ensuring that the folder exists as part of an init script.