Monday morning: the tunnel that came up on Friday is gone, the interface is still listed, and nothing in the journal says anyone noticed. The host is online, the dashboard is green, and whatever it sent over the weekend left through the physical interface instead. Two independent decisions are missing here, one about whether the client process survives a transient failure and one about whether anything above it starts the process again after it exits. Fixing either one alone leaves the other gap open.

Start from what the unit actually did, not from what the monitor claims. systemctl status openvpn-client@office and journalctl -u openvpn-client@office -n 50 show the exit reason and the last line the client wrote before it left.

The Process Exited Before Anyone Noticed

A client that disappears without an error usually exited on purpose. The profile decides that behaviour, not the service manager: ping-exit ends the process as soon as the peer stops replying, while ping-restart keeps the process and reconnects inside it. Session caps and inactivity timers produce much the same picture from outside, with no tunnel and no alarm.

The two ping directives cannot both appear in one profile, so pick one and record the choice. Look at the server too, since its own ping-exit closes a session whatever the client requested, and only the server log records who made that call.

Pick Between ping-exit and ping-restart

Choose ping-restart for a laptop or a remote site that should heal itself, and reserve ping-exit for cases where a dead tunnel must stop the process so something else can act on it. The numbers matter less than the relationship: ping 10 with ping-restart 60 means ten seconds of silence before a probe and sixty before the restart, which is aggressive on a lossy mobile link and reasonable on a wired one. Whatever you pick, write the reason next to the line, because the next reader will otherwise assume the defaults were deliberate.

Then confirm that the process is really what exited. A unit that reports active while the tunnel is dead is a different failure, handled further down.

Supervision That Actually Restarts the Unit

On a systemd host, the smallest durable change is one drop-in file: Restart=on-failure and RestartSec=10 in /etc/systemd/system/[email protected]/restart.conf. A drop-in is only read when systemd reloads its own definitions, so run systemctl daemon-reload afterwards. Verify with systemctl show -p Restart -p ExecMainStatus openvpn-client@office rather than assuming the value landed. The instance in the filename has to be the profile that unit really loads, so a file written for office does nothing for openvpn-client@home.

on-failure ignores one case: a clean exit whose status is zero. Some teardown paths end that way, so read the recorded status instead of trusting the wording of a man page. If your client gives up with a zero, Restart=always is what you need, and the cost is that a genuinely broken profile keeps coming back until the start rate limit trips and the journal fills.

Restart=always also fires after a deliberate stop. Use systemctl stop for maintenance, and mask the unit if it has to stay down while you work.

Catch the Leak while the Tunnel Is Down

Supervision keeps the tunnel coming back; it does not stop traffic from leaving while the tunnel is gone. persist-tun keeps the device and its routes across reconnects, which is convenient and opens a window. The device survives, the routes still target it, and packets drain out unprotected and unreported. That is a policy choice, not a neutral default.

When a host may not emit unprotected packets at all, only the firewall can guarantee it. An output rule that permits the tunnel interface and the VPN server's address while dropping everything else keeps holding after the client dies, and nothing in the client's own configuration can filter traffic the client is not carrying.

Test it by stopping the client on purpose. Run systemctl stop openvpn-client@office, then curl -m 5 https://example.com, which should fail instead of succeeding over the physical link. A success means the firewall rule is missing or too permissive.

Reconnect, confirm the tunnel carries traffic again, and only then add the check to monitoring. Polling ip addr from cron for a tun device is the supervision that fails most often, because with persist-tun the device outlives the session and the probe reports healthy while nothing is being carried.

Ũhoro ũhĩtĩte