eXistenZ | Stefan

Remote Kodi video playback (Part 3 – SSHFS)

Still here? Still waiting?
I would have given up.

Oh well, here goes:

In part 1 and part 2 I talked about the various existing options for connecting a remote Kodi device to my NAS so I would have access to my media remotely.
It also became clear after a bit of testing and tweaking, that neither OpenVPN nor Samba were going to work due to latency and slower throughput than required.
So, I re-evaluated my options and SSHFS, which in the beginning looked pale in comparison to the already tested out alternatives, suddenly didn’t look so bad anymore.

Sure, I had to set up some extra configuration, it was a bit more work security wise, and SSHFS wasn’t available on OpenELEC, but if I could solve those things I still might have a shot at smooth 1080p playback after all.

Installation of SSHFS

A I mentioned, SSHFS is not available for Kodi on the ARM architecture, which is what a Raspberry Pi is.

Not because it’s hard to compile, but simply because it’s not used by many, so the developers of Kodi couldn’t be bothered to compile and package it.
Disclamer: I got this statement from one of the developers on IRC when I discussed, so I’m not making stuff up here.

Debian is available for the Raspberry Pi as Raspbian, and since it’s a complete Debian installation, SSHFS is available too.

So, I tried downloading the .deb onto my Pi and after some extracting I ended up with the sshfs executable. When I ran the executable it turned out that it just works!

It seems that SSHFS has no dependencies or is statically compiled or something like that, but hey, let’s not tire ourselves with de details, it works and that’s what counts!

Get it here: http://archive.raspbian.org/raspbian/pool/main/s/sshfs-fuse/

Configuring it

On the Pi

I created a .bin directory and put sshfs inside of it, so I ended up with /storage/.bin/sshfs as an executable.
Now all I had to do on the Pi was set up some SSHFS mounts towards my NAS. I put these in two systemd services, each mount in their own service like so:
The SSH user I used throughout the configuration is mrkitten in these code snippets.

[Unit]
Description=SSHFS-NAS -- FILMS
After=network-online.service
Requires=network-online.service

[Service]
Type=forking
ExecStart=/storage/.bin/sshfs -o reconnect /storage/nas/films mrkitten@nas.domain.com:films
ExecStop=/usr/bin/fusermount -u /storage/nas/films
TimeoutStopSec=1
Restart=on-failure
RestartSec=20

[Install]
WantedBy=multi-user.target
[Unit]
Description=SSHFS-NAS -- SERIES
After=network-online.service
Requires=network-online.service

[Service]
Type=forking
ExecStart=/storage/.bin/sshfs -o reconnect /storage/nas/series mrkitten@nas.domain.com:series
ExecStop=/usr/bin/fusermount -u /storage/nas/series 
TimeoutStopSec=1
Restart=on-failure
RestartSec=20

[Install]
WantedBy=multi-user.target

Because I found it to be convenient to connect to the remote Pi from the NAS, I created a third systemd service which opens a remote SSH tunnel. This tunnels allows me to connect to localhost on port 22001 on my NAS, which ends up on the remote Pi.

After a bit of research it turns out that once a SSH connection is gone it will no longer restore itself. That is why I installed the little tool autossh via the Kodi interface, and wrapped my SSH command in autossh. The parameter -M 20000 opens a control connection on port 20000, as soon as that connection dies, a new SSH tunnel is set up.

The complete systemd script is pretty self explanatory and looks like this:

[Unit]
Description=SSH-NAS
After=network-online.service
Requires=network-online.service

[Service]
Type=forking
ExecStart=/storage/.kodi/addons/tools.autossh/bin/autossh -M 20000 nas.domain.com -f -N -R 22001:localhost:22
TimeoutStopSec=1
Restart=on-failure
RestartSec=20

[Install]
WantedBy=multi-user.target

These three systemd scripts were then of course set up to start on boot with systemctl enable sshfs-nas-xbmc.service etc.

On the NAS

The Pi side was done, but on my NAS I had to configure some things as well.

I created the mrkitten user on my NAS, and set up OpenSSH to only allow SFTP for the user and to lock that user in its home directory:

[...]
Match User mrkitten
  ChrootDirectory /home/mrkitten
  ForceCommand internal-sftp
  X11Forwarding no
[...]

Then I created the two directories the Pi is trying to mount with sshfs(films and series) inside mrkittens home dir.

After the creation and distribution of a SSH keypair, mrkitten could access my nas and mount the directories by making use of the pubkey, but would stay locked in its home directory /home/mrkitten with nowhere to go. Security: check.

The problem with this was that my films and series lived outside mrkittens homedir, and since we locked him in there, there was no way to actually access those resources.

To work around this I bind mounted my actual storage on the two directories I created earlier on:

/actual-storage/films  /home/mrkitten/films  none bind 0 0
/actual-storage/series /home/mrkitten/series none bind 0 0

Since the SSH user mrkitten could access the directories films and series via SSHFS which in turn were bind mounted to the actual storage, Kodi could now see and index all the stored films and series on my NAS, available locally on the Pi as /storage/nas/films and /storage/nas/series.

Rejoice

I already knew that SSH and SSHFS were capable of using all 4 cores of the Pi for decryption of the SSH connection, and this was exactly what I needed.

SSHFS brought smooth 1080p playback of all my favorite kitten movies without stutter or interruption, via the internet, to the remote Pi in another village in my country.
Both the NAS and the Pi are hooked up to a 50Mbit fiber connection, which is all you ever need for 1080p or below.

In the end though, the whole cat setup was kinda useless: I am more of a dog guy.

happydog