I picked Import from file… in GNOME Settings, chose a profile that works with the vendor client, and the dialog closed without adding anything to the list. On a second laptop the import completed, the connection appeared under the profile's name, and then it failed at the first authentication prompt. NetworkManager never runs your .ovpn or wg-quick file as-is. It hands the file to a parser, the parser turns it into NetworkManager's own connection format, and from then on the tunnel is built from that parsed object — secrets, routes, DNS and all. So the useful question is not why the file is broken, but whether the parse happened and what it kept.

What the import actually does with the file

For OpenVPN, the parser lives in the plugin package, and the connection it creates points at a D-Bus service such as org.freedesktop.NetworkManager.openvpn. No plugin, no parser: the type is unknown to nmcli, and the graphical add-VPN list may show no import entry at all. WireGuard differs in one important way — NetworkManager has carried its own WireGuard settings since the 1.30 series, so there is no separate plugin package, but the wg-quick reader only exists in builds that ship it.

Either way the file is read once. The result is written as a keyfile under /etc/NetworkManager/system-connections/, named after the connection, owned by root and unreadable by other users because it holds the key material. That keyfile is the connection now; editing the original .ovpn afterwards changes nothing.

Three symptoms belong to three different stages. No import entry or an unknown type means the plugin or version is missing. An import error that names a directive means the parser read the file and rejected part of it. A connection that exists but never activates means the parsed object is incomplete or the server side is refusing it. Decide which one you have before editing anything.

Confirm the plugin before you debug the profile

A missing plugin looks exactly like a corrupt profile, so check the package first. On Debian and Ubuntu the OpenVPN support ships as network-manager-openvpn plus a desktop helper; on Fedora the packages are NetworkManager-openvpn and NetworkManager-openvpn-gnome; on Arch it is networkmanager-openvpn.

dpkg -l network-manager-openvpn-gnome | tail -n 2
rpm -q NetworkManager-openvpn
pacman -Q networkmanager-openvpn

Then import from an absolute path: nmcli connection import type openvpn file /home/you/profile.ovpn. Relative paths usually work, but a shell that has changed directory turns a quick import into a detour. For WireGuard, check nmcli --version and make sure the kernel side exists with modprobe wireguard; an import that succeeds on a machine without the module leaves you with a connection whose device never appears. The nmcli reference documents the import subcommand and the accepted type names. If type wireguard is rejected outright, the build predates the feature, and the correct move is a distribution package or backport — not copying the configuration into an arbitrary directory and hoping something reads it.

Read the OpenVPN connection, not the .ovpn

Once the connection exists, read the parsed settings instead of rereading the file: nmcli connection show "Work VPN" | grep -E '^vpn\.'. You want the remote and port, the transport, the identity material — ca, cert, key, tls-auth or tls-crypt — and the authentication method. On a profile with a private key password, add sudo nmcli --show-secrets connection show "Work VPN" and look at the secret flags: 0 is none, so the secret sits in the keyfile; 1 is agent-owned; 2 is not-saved, meaning it is never written to the keyfile; 4 is not-required, meaning no secret is needed at all. They are bits, not a scale, so 3 is simply agent-owned plus not-saved. A secret that prompts you once per session is agent-owned (1) with the agent asking for it; there is no separate flag number for that. A flag mismatch is the usual reason a profile connects from the desktop applet and fails from a script or at boot.

The quickest way to see what the parser dropped is to ask the plugin to write the file back, then diff it: nmcli connection export "Work VPN" /tmp/roundtrip.ovpn. Directives that disappear in that diff will not exist at connect time. Hooks are the usual suspects — script-security, up, down and route-up expect a script to run with elevated rights and are deliberately not carried over. Do not lower verification or grant extra privileges to make an import succeed; an unsupported option usually reflects the plugin's feature set rather than an unreachable server. Move that behaviour into a NetworkManager dispatcher script or into server-side policy.

Also confirm the identity fields survived: the CA reference, remote-cert-tls, and any name check the profile relied on. A connection that comes up without them may be talking to whatever answers on that address.

Read the WireGuard connection, not the wg-quick file

A wg-quick file is a format with shell semantics; the imported connection is a set of settings. PrivateKey becomes the interface private key, Address becomes one or more IPv4 and IPv6 addresses, DNS maps to NetworkManager's resolver properties, MTU maps to wireguard.mtu (wg-quick's own default is 1420), and each peer block becomes a peer entry with public key, endpoint, allowed IPs and persistent keepalive. Print what was stored with nmcli --show-secrets connection show wg0; if the peer list does not show up in that output, read the keyfile:

sudo sed -n '/^\[wireguard\]/,/^\[/p' /etc/NetworkManager/system-connections/wg0.nmconnection

What does not survive is the shell half of wg-quick. PreUp, PostUp, PreDown, PostDown and Table are behaviour of that tool, not attributes of a WireGuard interface, so nothing runs them after an import. If the original used Table = off to leave the default route alone, recent NetworkManager releases expose ip4-auto-default-route and ip6-auto-default-route for the same purpose; set them explicitly instead of assuming the connection behaves like the script. A hook that pushed a custom route needs that route added to the connection's routing settings, or it will simply be missing.

Give the connection exactly one owner

The classic follow-up failure is a connection that works until the next boot and then loops. Usually [email protected] was still enabled from an earlier experiment, or a vendor client was launching its own daemon, and two owners were writing routes and DNS for the same destination. NetworkManager sets the resolver through its own path, wg-quick writes through resolvconf, and the last writer wins — so name resolution works, then stops, then works again. Check systemctl status wg-quick@wg0, nmcli connection show --active and ip link show type wireguard, then disable the second owner rather than tuning its metric.

If you genuinely need both, give them separate interfaces and disjoint allowed IPs, and let exactly one of them install the default route. Two default routes with different metrics is not a split tunnel; it is a race decided by whichever service starts second. And after a reconnect, inspect the applied state again — a one-off manual resolver edit that makes things work is not evidence that the import is complete.

Verify with traffic and survive a reboot

Bring the connection up with nmcli connection up "Work VPN", then read state, address and routes instead of trusting the icon: nmcli device show wg0 | grep -E 'GENERAL.STATE|IP4.ADDRESS|IP4.ROUTE', ip route show default, and a real lookup of a name that only resolves inside the tunnel. A handshake or a successful ping only proves the crypto works; it says nothing about forwarding, split-tunnel prefixes or private DNS, which are the parts that usually break.

Then reboot and repeat it. Autoconnect behaviour, a renamed interface and a plugin that loads after the device are all failures you only see on a fresh boot. journalctl -u NetworkManager -b --no-pager | tail -n 40 shows what the daemon did with this connection in this boot. For a second desktop, copy the keyfile and keep it root-owned with mode 600, or use nmcli connection export for OpenVPN and re-import the resulting .ovpn — the export path has no WireGuard equivalent, so that direction is a file copy or a fresh import from the protected original.

Short version, in order: confirm the plugin or NetworkManager version, import from an absolute path, read the parsed settings including secret flags, diff the OpenVPN export against the original, check hooks and routes on the WireGuard side, disable any second owner, then verify a name lookup and the route table after a reboot. Once a connection passes all of that, the profile file that started it can go back into protected storage.

ဆက်စပ်ဆောင်းပါးများ