Mount on VPN Connect

From Tech Tangents
Revision as of 18:46, 22 August 2024 by Akbkuku (talk | contribs)
Jump to navigation Jump to search

I use a VPN to my server from my laptop which can happen from effectively "anywhere". But I also don't always want to connect to my server so I use the KDE Network Manager to manually connect with through GUI only when needed. This causes issues when it comes to mounting remote filesystems because the server isn't always available.

This is my solution for an adhoc drive mount over and unpredictable VPN connection. This uses Systemd due to its ability to add dependencies which make it more robust. I'm also only going to be covering SMB. In my experience NFS is inferior in performance consistency even in an all Linux environment.

Starting Point

On your server you need to setup a typical Samba setup[1]. Make sure you can mount your share on your client computer using other methods like mount or /etc/fstab.

I'm also going to be using Wireguard[2] but there isn't anything unique to that for this setup. Note that we do not need proxy forwarding for this.

VPN Network Interface Target

In order to prevent the mounts from attempting to access the server when it is unreachable we need to set the VPN connection as a dependency of the Systemd mount. This is not the same as network-online.target. We can use a specific network interface device as a target, but you need to find what yours is called.

You can list all targetable NICs for Systemd using the following command:

systemctl list-units --no-pager | grep net-device

You'll be given a result similar to this:

sys-subsystem-net-devices-docker0.device                 loaded active plugged   /sys/subsystem/net/devices/docker0
sys-subsystem-net-devices-enp45s0.device                 loaded active plugged   Killer E3000 2.5GbE Controller
sys-subsystem-net-devices-enx9cebe850e460.device         loaded active plugged   Dell D3100 Docking Station

The list can be much longer depending on your system. To more easily find your VPN interface you can run the command before and after connecting and look for the new line that will be added. For reference, here is how my Wireguard connection was shown:

sys-subsystem-net-devices-Videos\x2dLocal.device         loaded active plugged   /sys/subsystem/net/devices/Videos-Local

I will be using sys-subsystem-net-devices-Videos\x2dLocal.device as my target for service unit scripts.

Systemd Mount and Automount

Systemd can manage the mounting of filesystems as unit files. These are just plain text files that are easily configurable for different needs. On Ubuntu, as an example, they are located in /etc/systemd/system/. We are going to make a mount and automount service for each share you want to mount to after connecting to the VPN.

Mount Service File

The SMB/CIFS settings for the mount go in the mount script. The settings you need for this will be dependent on your server setup but the one I'm using here are a decent general purpose solution.

opt-videos.mount
[Unit] 
Description=SMB Share
OnFailure=automount-restarter@%N.service

[Mount]
# Server share path over VPN
What=//10.0.10.1/videos 
# Local mount directory
Where=/opt/videos 
# SMB mount options
Options=credentials=/etc/smb.conf,vers=3.1.1,uid=1000,iocharset=utf8
Type=cifs 
TimeoutSec=30

Some notes about different settings in there:

  • credentials: The path to a file that stores the user auth for connecting to the samba server[3]
  • uid: The user ID number for the user on the server you want the file modifications to be saved as.
  • opt-videos.mount: The filename for the unit file must match the path set in Where= with directory delimiters (/) replaced with hyphens.

We'll get to OnFailure below as it is a workaround for a Systemd quirk.

Automount Service File

The mount file lacks an [Install] directive meaning it is not run during startup. The automount file does and by sharing the same filename will watch for filesystem access of the mount path to automatically call the mount file. It also has the dependencies to know to run only after the network interface is connected.

opt-videos.automount
[Unit]
Description=SMB Share Automount
OnFailure=automount-restarter@%N.service
# Network interface target dependancies
After=sys-subsystem-net-devices-Videos\x2dLocal.device
Requisite=sys-subsystem-net-devices-Videos\x2dLocal.device

[Automount]
Where=/opt/videos

[Install] 
WantedBy=multi-user.target

The name of the automount file must be the same as the mount file and also requires the Where= value for the mount path. Note that we are using Requisite= instead of Requires=. Like requires, requisite will make the target in After= a dependency. Unlike requires, requisite will not attempt to launch the target and instead will terminate as a failure immediately if it is not running. In this application this prevents Systemd from waiting for the VPN connection to start when it may or may not be connected depending on what the user is doing. This will also call the OnFailure service that we will get to in a moment.

Self Starting

If you connect to your VPN and start the automount service the filesystem should be mounted when you attempt to access the mount path. If you attempt to enable the service and reboot though, it will fail and stay terminated. There is no built in feature of Systemd to re-attempt to start on failure. This is where the last unit file comes into play. This is based on a solution responding to an issue to this very problem on Systemd's git repository[4].

automount-restarter@%N.service
[Unit]
Description=automount restarter for %i

[Service]
Type=oneshot
ExecStartPre=/usr/bin/sleep 10
ExecStart=/usr/bin/systemctl restart %i.automount

This is a service that the mount and automount files will call on failure. It will wait 10 seconds and then call back the service that called it. Being a oneshot service means that it will instantly exit and not persist, so you will not build a growing stack of services calling each other.

Functionally, this means that after booting your computer will attempt to start the automount service every 10 seconds, and if you are not connected to your VPS it will never attempt to mount it. This is the most flexible solution to this problem I have found so far and is easily adaptable to add additional mounts by creating more Systemd files.