Mount Remote Filesystems Using sshfs and systemd

This is an update to an earlier post I made. This post uses a systemd user service instead of a global systemd service (that lives in /usr/lib/systemd/system and runs as root or some other user explicitly configured).

Prerequisites

  1. SSHFS (sudo apt install sshfs)

In this example

  1. Remote host user: bob
  2. Remote host address: example.com
  3. Remote directory to be mounted locally: /home/bob/disk-1
  4. Local directory where above remote directory is to be mounted: /home/alice/disk-1
  5. We assume local user alice has SSH access to the remote accountbob@example.com that is, alice's SSH public key (typically) exists in /home/bob/.ssh/authorized_keys
  6. alice has her SSH keypair stored in the standard location at /home/alice/.ssh named id_rsa and id_rsa.pub (If elsewhere, the IdentityFile= option for sshfs can be used to specify the path to the private key

At the end of this example, files stored in /home/bob/disk-1 on the remote machine (example.com) should become accessible on the local machine at /home/alice/disk-1.

Steps

  1. User alice creates a local folder to be used as a mountpoint for the remote folder
    mkdir $HOME/disk-1
  2. Create a systemd user service
    mkdir -p $HOME/.config/systemd/user
  3. Create a file $HOME/.config/systemd/user/mnt-disk-1.mount with the following content:
[Unit]
Description=Mount disk-1 with sshfs
After=network-online.target
Wants=network-online.target

[Install]
WantedBy=default.target

[Mount]
What=bob@example.com:/home/bob/disk-1
Where=/home/alice/disk-1
Type=fuse.sshfs
Options=_netdev,reconnect,ServerAliveInterval=30,ServerAliveCountMax=5,x-systemd.automount
TimeoutSec=60

4. Register the newly created systemd mount

systemctl --user daemon-reload
systemctl --user enable mnt-disk-1.mount

To mount the remote directory:
systemctl --user start mnt-disk-1.mount

To unmount the remote directory:
systemctl --user stop mnt-disk-1.mount

To check the status of our systemd user mount:
systemctl --user status mnt-disk-1.mount

Note

Additional SSHFS options can be supplied in the Options= section of the systemd mount file. Among those that are particularly useful are setting allow_other along with uid and gid so that new files created by alice will be owned and accessible by a specific remote user.

You can add Cipher=arcfour to the end of Options= if you're using this to mount a filesystem on the Raspberry Pi. Note that this would use a weaker cipher for the SSH connection.

In systemd user service files, you can use %h to refer to the user's home folder in place of /home/alice.

All is Not Well...Yet

The above systemd user mount works well...most of the time. What happens when you encounter a network failure? Well, that may be handled. But what happens when there is no network? What happens when a certain network interface on which example.com is accessible goes down? What happens when you leave your "home network" on which example.com exists?

We've supplied the reconnect option along with ServerAliveInterval and ServerAliveCountMax parameters for sshfs to determine when the connection has broken. So that means it will keep trying to reconnect and work perfectly, right?

In practise, when you turn off your network interface, your file manager's UI may freeze. The mount point may freeze.

If only systemd could have a Restart=on-failure option for mounts so we could configure sshfs options to fail fast and just have systemd restart the mount, right? That feature request is ~6 years old. If only systemd mounts could react to network states for devices in NetworkManager. Turning off eth0 in network manager does nothing to the sys-subsystem-net-devices-eth0.device systemd unit; it still stays loaded    active   plugged.

Using a systemd User Service

If you are affected by the system behaviour described above, remove the above mount file and create a systemd user service instead.

Here, we run sshfs in foreground mode with -f and configure it to fail fast (in 10 secs). After the sshfs process failure is detected by systemd, it will restart the process for us after 20s, provided rate-limiting parameters StartLimitIntervalSec and StartLimitBurst are met (a maximum of 10 starts in 5 minutes).

[Unit]
Description=Mount disk-1 with sshfs
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=10

[Install]
WantedBy=default.target

[Service]
Type=exec
ExecStart=/usr/bin/sshfs -f bob@example.com:/home/bob/disk-1 /home/alice/disk-1 -o rw,allow_other,idmap=user,uid=1000,gid=1000,ServerAliveInterval=10,ServerAliveCountMax=1,_netdev
ExecStop=/usr/bin/umount /home/alice/disk-1
Restart=on-failure
RestartSec=20
$HOME/.config/systemd/user/mnt-disk-1.service

Register the newly created systemd service

systemctl --user daemon-reload
systemctl --user enable mnt-disk-1.service

To mount the remote directory:
‌systemctl --user start mnt-disk-1.service

To unmount the remote directory:‌
‌systemctl --user stop mnt-disk-1.service

To check the status of our systemd user service:‌
‌systemctl --user status mnt-disk-1.service