A web application which requires a Samba-Share (cifs) via openvpn (IPv6) runs on a Debian server (jessie, systemd 215). With the naive configuration, manual starting and stopping works just fine, but rebooting doesn't work properly. Naive configuration:
apache2
cifs-utils
openvpn
/etc/fstab
configured/etc/openvpn/client.conf
When you start everything individually, it works with no problem: - systemctl start [email protected]
mount /var/www/data
systemctl start apache2.service
Stopping also works fine manually: - systemctl stop apache2.service
umount /var/www/data
systemctl stop [email protected]
But with a reboot, you can't start up... - When starting, the mount is attempted before the VPN is available and, of course, it fails.
... or shut down: - The VPN was interrupted before the umount was completed.
The solution shouldn't be too difficult with systemd units. Since no dependencies can be explicitly formulated in /etc/fstab
, a unit file is created for the mount. We start with the automatically generated unit file:
systemctl cat var-www-data.mount > /etc/systemd/system/var-www-data.mount
And we delete the entries SourcePath
and Documentation
, so that we're left with just the minimum:
#/etc/systemd/system/var-www-data.mount
[Unit]
Before=remote-fs.target
[Mount]
What=//v6.smb.example.com/WwwDataShare
Where=/var/www/data
Type=cifs
Options=ro,guest,iocharset=utf8
Then the entry from /etc/fstab
is deleted, and the unit is activated with: systemctl enable var-www-data.mount; systemctl daemon-reload
It should now be possible to properly mount and unmount /var/www/data
.
Now we can formulate the dependency on openvpn:
#/etc/systemd/system/var-www-data.mount
[Unit]
Before=remote-fs.target
[email protected]
[email protected]
systemctl daemon-reload
Still doesn't work, unfortunately. After various analyses with journalctl -f
, it became apparent that
First, it needs a script to check the preconditions for starting (ping
) and stopping (umount
): /etc/openvpn/checks_updown
#!/bin/bash
LOGGER_RED="systemd-cat -t $0 -p err"
LOGGER_BOLD="systemd-cat -t $0 -p notice"
LOGGER_NORM="systemd-cat -t $0 -p info"
case "$1" in
ping)
while true
do
if ping6 -q -c 3 v6.smb.example.com > /dev/null 2>&1
then
echo ping6 ok | $LOGGER_BOLD
exit 0
else
echo "." | $LOGGER_NORM
sleep 4
fi
done
;;
umount)
while true
do
if mount | grep "//v6.smb.example.com/" >/dev/null 2>&1
then
echo ";" | $LOGGER_NORM
sleep 4
else
echo umount ok | $LOGGER_BOLD
exit 0
fi
done
;;
*)
echo "invalid call: $1" | tee | $LOGGER_RED
exit 1
;;
esac
For this script, we are building our own unit: ```ini
[Unit] Requires=[email protected] After=[email protected]
[Service] Type=oneshot RemainAfterExit=yes ExecStart=/etc/openvpn/checks_updown ping ExecStop=/etc/openvpn/checks_updown umount
[Install] RequiredBy=var-www-data.mount
The `RemainAfterExit=yes` causes (along with `oneshot`) `ExecStop` to only be executed when this unit is stopped. Without this setting, `ExecStop` would be executed immediately after `ExecStart`, while start-up is still in progress. Expand dependencies in the `mount` unit:
```ini
# /etc/systemd/system/var-www-data.mount
[Unit]
Before=apache2.service
Requires=vpnbarrier.service
After=vpnbarrier.service
[Mount]
...
[Install]
RequiredBy=apache2.service
systemctl enable vpnbarrier.service; systemctl daemon-reload
Only now does everything work as it should:
systemctl stop [email protected]
: First apache2 was stopped, then /var/www/data
was suspended, and only after that, the VPN was stopped.systemctl start apache2.service
: First the VPN was started, then the cifs-mount and finally apache2.Requires
and After
. That's the only way to get shut-down under control, too.vpnbarrier.service
unit and properly integrating the "ping"- and "umount" check with entries in *.conf.d
directories?systemd daemon-reload
, and a reboot had to be done before everything worked as expected.