You finish the MFA prompt, the tunnel comes up, and closing the terminal takes the connection down with it. That is a supervision problem rather than an authentication problem, and OpenConnect already ships the switch that solves it. The fix is to let the client fork into the background after startup finishes, once the interactive part is genuinely over. What follows is a sequence of checks: work through them in order, and stop at the first one that does not hold for your gateway.

Confirm what the gateway demands at login

Before you type a command, write down the credential path the deployment enforces. Certificate only, password plus a token, and a browser round trip through a SAML provider behave differently from each other, and background mode cannot skip any of them. The option changes what happens after startup, never what happens during it.

The tempting workaround is to automate the prompt instead. A wrapper that types a fixed answer whenever it recognises a password prompt breaks the moment the gateway asks for a one-time code, and it leaves a credential sitting in a file that other accounts can read. If a person has to approve the session, keep the person in the loop.

Run the first session in the foreground and read the output

Connect normally once and let the entire handshake print. Note the protocol in use, the certificate or token path, the tunnel address the server assigns, and every warning emitted before the connection is accepted. That transcript is your baseline, and it is the only cheap way to tell a client problem from a gateway change later on. Save it somewhere outside the terminal buffer.

Then repeat the same invocation with background mode and a PID file added, for example openconnect --background --pid-file /run/openconnect.pid vpn.example.net, keeping the protocol and authentication options your gateway requires on the same line. The OpenConnect manual describes that option as continuing in the background after startup completes, which is exactly why the interactive phase has to be finished first.

Make the running process findable and stoppable

A PID file is only evidence while it matches a live process. Put it in a directory the service account owns, and compare the recorded number against the process table before you signal anything. Reboots and crashes leave the file behind, and a stale file is the usual reason a stop script reports success while the tunnel is still up. Treat the check as part of the stop procedure, not as an optional sanity step.

Signal the verified PID, then confirm the tunnel interface has actually disappeared rather than trusting the exit status. If the client needs elevated privileges to configure the interface, the signal has to come from an account that is allowed to send it.

Do not stack background mode under a supervisor

systemd and similar supervisors expect to own the process they launched, which is why a client that forks away confuses them. The supervisor watches a launcher exit while the real connection lives on, so restart logic, status reporting and stop timeouts all describe something that is no longer true. Write the unit in the supported foreground arrangement and let the supervisor do the daemon work.

Reserve --background for sessions a person starts and then walks away from. If the requirement is a tunnel that exists before anyone logs in, the missing piece is an approved noninteractive identity plus a plan for renewing it, and no command-line flag supplies either one. Adding the flag to a boot script produces a tunnel that fails quietly at the first expired credential.

Treat the session cookie as a credential

OpenConnect documents a separate authentication phase through --authenticate, and the resulting material can be handed back with --cookie-on-stdin. That pair exists for integration work, and what it produces is as sensitive as the password that created it.

Keep the value out of shell history, out of logs, and out of any ticket you open. A handoff script also has to preserve the verified endpoint information the client received alongside the cookie; drop that and a later run may connect to a host you never authenticated, which is worse than a connection that simply fails.

Work through the list before you close the terminal

Four things should be true: the interactive login finished in the foreground, the PID file points at a process you verified, the supervisor question is settled one way or the other, and the cookie has a storage plan that is not a plaintext file. When all four hold, walking away from the terminal is safe and the tunnel keeps running.

If one of them fails, fix that item before touching the others, because the remaining checks cannot compensate for it. Keep the foreground transcript from your first run as well: the next time the tunnel drops without warning, that baseline is what separates a gateway-side change from a client-side one.

Qillqakuna t'inkisqa