I backup my laptop using Syncoid from the Sanoid package to my homeserver. Because I don’t want to do this manually (e.g. forget it), I was looking for a way to automate the whole thing. A systemd-timer seems like a simple solution at first, but the system is not online all the time and also switches between networks. Also my backup destination is not accessible from the outside without VPN. So I need a solution which only runs if the laptop connects to the home network.

Because I use NetworkManager, I can make use of the NetworkManager-dispatcher The dispatcher is a service that runs user provided scripts upon changes in NetworkManager.

You need to outsource the syncoid command to a systemd-service, because dispatcher has a default timeout of 20 seconds. You can avoid it, but this feels like a rather hacky solution.

A sample systemd service could look like this:

/etc/systemd/system/syncoid-server-brand-backup.service

[Unit]
Description=Sync local ZFS Filesystem to Backup Target
Requires=zfs.target
After=zfs.target
 
[Service]
Type=exec
ExecStart=/usr/sbin/syncoid -r --sendoptions="w" zroot/encr root@server.del.brand-web.net:tempest/backup/clients/T480

The Type=exec is important, because then the service manager will then consider the unit immediately started after the binary has been executed. Otherwise you have the said timeout problem. After you created the service, you need to reload the daemon with systemctl daemon-reload.

The dispatcher script can access many environment variables to get informations about the network the devices connects to.

For me the variable CONNECTION_UUID is interesting. If the connection UUID (you can get it from nmcli con show) match the one from my home wifi connection, then the script should start the service.

A (very simple) example:

/etc/NetworkManager/dispatcher.d/99-syncoid-backup.sh

#!/bin/sh
#Your Connection UUID here
uuid=0f48fb19-2148-4762-9f88-dd0560951fdb

interface=$1 status=$2
if [ "$CONNECTION_UUID" = $uuid ]; then
  case $status in
    up)
      systemctl start syncoid-server-brand-backup.service
      ;;
  esac
fi

Thats it. If the connection gets activated, the script should start the systemd service:

Apr 17 13:07:04 jantop dbus-daemon[1013]: [system] Activating via systemd: service name='org.freedesktop.nm_dispatcher' unit='dbus-org.freedesktop.nm-dispatcher.service' requested by ':1.5' >
Apr 17 13:07:04 jantop systemd[1]: Starting Network Manager Script Dispatcher Service...
Apr 17 13:07:04 jantop dbus-daemon[1013]: [system] Successfully activated service 'org.freedesktop.nm_dispatcher'
Apr 17 13:07:04 jantop systemd[1]: Started Network Manager Script Dispatcher Service.
Apr 17 13:07:04 jantop NetworkManager[1014]: <info>  [1618657624.5117] device (wlp3s0): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'managed')
Apr 17 13:07:04 jantop NetworkManager[1014]: <info>  [1618657624.5124] device (wlp3s0): state change: secondaries -> activated (reason 'none', sys-iface-state: 'managed')
Apr 17 13:07:04 jantop NetworkManager[1014]: <info>  [1618657624.5140] manager: NetworkManager state is now CONNECTED_GLOBAL
Apr 17 13:07:04 jantop dunst[2444]: WARNING: No icon found in path: 'nm-signal-75'
Apr 17 13:07:04 jantop NetworkManager[1014]: <info>  [1618657624.5196] policy: set 'Benni&Janni' (wlp3s0) as default for IPv4 routing and DNS
Apr 17 13:07:04 jantop NetworkManager[1014]: <info>  [1618657624.5279] device (wlp3s0): Activation: successful, device activated.
Apr 17 13:07:04 jantop systemd[1]: Starting Sync local ZFS Filesystem to Backup Target...
Apr 17 13:07:04 jantop systemd[1]: Started Sync local ZFS Filesystem to Backup Target.