Suspend the machine, resume it, then check three things in this order before you touch any configuration: whether tun0 still exists, whether the route to an internal address still picks it, and whether the server still lists this peer. A device that survives sleep while the route points elsewhere is a leftover, not a tunnel. When the route is right and traffic still dies, the fault sits above the tunnel and restarting the client will not change it. Automating a restart makes sense only after a manual test has shown which of those three cases you have.

ip -br address show tun0
ip route get 10.20.0.10
journalctl -u openvpn-client@office -b --no-pager | tail -30

Reproduce the Resume Before You Automate It

Suspending ends the encrypted session more often than it removes the device. The UDP flow that kept the tunnel alive stops, the server may drop the peer, and the client either notices and reconnects or keeps an interface with nothing behind it. An interface check on its own proves little, because a stale device looks exactly like a working one until packets have to cross it. Run the route lookup plus one real request across the tunnel, then read the journal around the moment of resume.

If the client comes back by itself, a hook adds churn instead of reliability. If it never recovers, automation is the honest fix.

Where a systemd Sleep Hook Actually Lives

Plenty of older guides point at /etc/pm/sleep.d, a directory owned by pm-utils and never consulted by a systemd-based suspend. systemd reads hooks from /usr/lib/systemd/system-sleep/ and /etc/systemd/system-sleep/, handing the phase first and the operation second, so pre and post are the only values a hook branches on. Keep the local copy under /etc instead of editing a packaged file, and remember the script runs as root in the middle of the transition, so it must return quickly.

#!/bin/sh
case "$1" in
  post)
    systemctl --no-block try-restart [email protected]
    ;;
esac
exit 0

try-restart touches a unit only when it is already active, so a tunnel you shut down on purpose remains down across the resume. --no-block keeps the hook from waiting while the client negotiates, which matters when the network has not come up yet. Together the two flags mean a hook that fails quietly instead of holding the whole resume sequence. Nothing happens at all when the unit is already stopped, which is exactly the outcome you want there.

Recover the Service, Leave tun0 Alone

Taking tun0 down by hand leaves the daemon supervising an interface it no longer owns, and the next state change produces confusing errors. Target the service or its connection profile rather than the interface; check the exact unit name first, because distribution packages, OpenVPN 3 and NetworkManager all choose different ones. A NetworkManager profile returns when that connection is cycled, so the systemd unit is not the target there. Whatever the mechanism, it should be the same action you verified by hand.

A restart reinstalls the routes the client pushed when it connected. Most resumes want that. A machine where you added paths of your own does not, so recheck those instead of assuming recovery restored them, and write them down where the next resume can find them.

Handle the Timing You Cannot Control

Wireless association and DHCP often finish after the hook has run, so a restart can fail while no path to the server exists yet. Wait briefly for that address, retry once, and log the result.

Name resolution is a separate race, because the desktop network stack may restore DNS after the tunnel is already up. Test lookups on their own with resolvectl query internal.example rather than inferring them from a working route. A tunnel that routes correctly and resolves nothing is a DNS problem, not a hook problem.

Keep the hook's decision visible by writing the phase, the unit name and the result into the journal. Record in the machine notes which resume test you ran, so a working recovery can be told apart from a lucky one. Choose the least disruptive action that brings service back, and let a client that recovers on its own do so. A full restart drops in-flight sessions, which is a real cost on a laptop that resumes several times a day.

Artihkkalat mat laktásit