Shutdowns that hang while a proxy is running are rarely a VPN bug, even when the VPN is the last thing visible on screen. Applications behind the proxy are still waiting for a path that is about to disappear, and the unit that owns the tunnel has not yet been asked to close it. What looks like a slow service is usually an ordering problem. Sequencing solves more of these than any timeout change.

Work outwards in reverse: consumers first, then the proxy, then the tunnel, each stopped by the component that started it.

List the units before stopping anything

Write down the application unit, the proxy unit and the VPN owner involved in a normal run. Add any resolver or helper with teardown of its own, since those are the ones people forget at two in the morning. Without that list, the first stop command you type picks a victim at random.

Names are weak evidence. A user proxy, a system proxy and another account's tunnel can share a name while having entirely unrelated lifecycles.

Finish the work, then stop the consumer

A planned stop begins with the application: let it finish or cancel its requests, then stop the proxy through its service unit. If the application should keep running after the tunnel goes away, arrange that deliberately rather than leaving it attached to a route that is about to vanish.

Requests that were in flight during the stop belong in the record, because that is where the retry storm comes from on the next start.

ExecStop and ExecStopPost are different instruments

ExecStop= is the synchronous stop operation; ExecStopPost= is cleanup that runs even after a failed start. A stop command that merely signals a process and returns lets systemd move on while the consumer is still flushing. Anything that must happen regardless belongs in the post variant, and anything that must block the stop belongs in the synchronous one. Inspect the effective unit and its drop-ins instead of editing a package file in place.

A dependency graph orders stop jobs. It does not turn an asynchronous script into a synchronous one, nor does it make a remote application commit its data.

Bound the stop and know what the bound costs

TimeoutStopSec= limits both the stop command and the service's own termination, and systemd escalates to a forceful kill when the limit expires. Choose the value from the application's real flush behaviour, and write down what may be lost when it hits. A number picked because the machine should power off faster is a data-loss setting in disguise.

When a stop is still slow, capture the unit, its child processes, the journal interval and the timeout result. Shortening every timeout or reaching for a broad kill is how clean shutdowns turn into corrupt state at the next boot.

Disconnect through the owner, then test three cases

Once consumers are down, ask the manager that owns the tunnel to disconnect: the systemd instance, the NetworkManager active connection, or the vendor service. Killing an unrelated OpenVPN process does not necessarily remove the session that supplied the route, and a proxy with a restart policy may recreate a request while you are dismantling the path. Coordinate that policy with the planned stop before you begin.

Test a normal stop, a stop with an active request, and a stop where the tunnel fails first. A repeatable sequence with a deadline beats a fast shutdown that works once.

Artitgels cun il medem tema