Configure VPN Client on Fedora

Fedora supports several VPN protocols out of the box through NetworkManager, and you can connect to a VPN graphically or from the terminal using nmcli.

You dropped the config file and nothing happened

You just received a .ovpn file from your provider or a .conf file for WireGuard. You double-click it and the file opens in a text editor. You run nmcli connection import and get Error: Unknown type 'openvpn'. You are not missing a step. Fedora ships with a modular network stack. The core NetworkManager daemon handles interfaces, DNS, and routing, but protocol support comes in separate plugins. You need the plugin that matches your VPN type before the system can process the configuration.

What is actually happening

NetworkManager acts as the abstraction layer between your desktop, the kernel, and network services. It manages the lifecycle of connections but does not implement encryption protocols itself. Think of NetworkManager as a traffic controller. It knows how to assign IP addresses and update routing tables, but it needs a specialist to handle the handshake and encryption for each protocol.

The VPN plugins are those specialists. When you install NetworkManager-openvpn, you add a translator that lets NetworkManager parse .ovpn files, launch the OpenVPN daemon, and inject the resulting routes into the kernel. Without the plugin, the config file is just text. With the plugin, it becomes a managed connection profile with state tracking, DNS integration, and automatic reconnection logic.

WireGuard works slightly differently. The WireGuard code lives in the kernel, but the plugin handles key management and interface creation. It bridges NetworkManager to the kernel module so you can toggle the tunnel from the GUI or CLI without managing wg-quick commands manually.

Install the matching plugin

Run the command that matches your VPN protocol. The package names include the protocol and the desktop integration component.

sudo dnf install NetworkManager-openvpn NetworkManager-openvpn-gnome
# The -gnome package adds the GUI integration for GNOME Settings.
# Without it, nmcli works but the desktop menu stays empty.

sudo dnf install NetworkManager-wireguard
# WireGuard is in the kernel, but this package provides the NM plugin.
# It handles key management and interface creation automatically.

sudo dnf install NetworkManager-libreswan NetworkManager-libreswan-gnome
# IPsec/IKEv2 support requires libreswan as the backend.
# The plugin bridges NetworkManager to the strongSwan/libreswan stack.

Reload NetworkManager to pick up the new plugin. Use reload instead of restart to keep your current network links alive.

sudo systemctl reload NetworkManager
# Reload is safer than restart. It re-reads plugins without dropping active connections.
# Restart kills all links. Reload keeps the network up while updating the daemon.

Reload the daemon before you import. NetworkManager caches plugin lists at startup.

Import the connection profile

You can import profiles from standard config files. nmcli reads the file, extracts the settings, and creates a connection profile in /etc/NetworkManager/system-connections/. The profile name comes from the config file. If the file lacks a name, nmcli generates a UUID-based name.

nmcli connection import type openvpn file ~/Downloads/client.ovpn
# nmcli parses the file and creates a connection profile.
# The profile name comes from the Config section in the .ovpn file.
# If the name is missing, nmcli generates a UUID-based name.

nmcli connection import type wireguard file ~/Downloads/wg0.conf
# WireGuard configs are INI-style. nmcli maps [Interface] and [Peer] sections.
# Private keys are stored securely in the keyring, not in plaintext config.

NetworkManager stores connection profiles in /etc/NetworkManager/system-connections/. These are text files. You can edit them, but nmcli is the safe way. Manual edits can drift from the internal schema. Use nmcli connection edit if you need to tweak routes or DNS manually.

Check the available profiles to confirm the import succeeded.

nmcli connection show
# Lists all saved profiles. Look for your VPN name in the NAME column.
# The UUID column helps if the name is ambiguous or contains special characters.

Check nmcli connection show. If the profile is missing, the import failed or the plugin is not loaded.

Connect and verify

Activate the connection using the profile name. NetworkManager handles DNS updates, routing, and credential prompts.

nmcli connection up "My VPN Profile"
# Activates the connection. NetworkManager handles DNS updates and routing.
# If credentials are needed, nmcli prompts on the terminal or uses the keyring.

nmcli connection show --active
# Lists all active connections. Look for your VPN profile in the list.
# The DEVICE column will show tun0 or wg0 depending on the protocol.

Verify that DNS is routing through the tunnel. DNS leaks happen when the system ignores the VPN's DNS servers and falls back to the physical interface.

resolvectl status
# Shows DNS servers per link. Your VPN interface should list the VPN's DNS.
# If the default route points to the physical interface, DNS might leak.
# NetworkManager usually sets the VPN as the default domain for DNS.

Run resolvectl status after connecting. If your DNS is still pointing to your ISP, your traffic is leaking.

Adjust routes and DNS

Split tunneling requires overriding the default route. Do not edit the config file manually after import. Use nmcli to modify the profile. This keeps the changes persistent and schema-valid.

nmcli connection modify "VPN Profile" ipv4.routes 10.0.0.0/8
# Adds a specific route without overriding the default gateway.
# This creates split tunneling for the 10.0.0.0/8 network only.
# The default route stays on the physical interface.

nmcli connection modify "VPN Profile" ipv4.ignore-auto-dns yes
# Disables DNS servers pushed by the VPN server.
# Useful when the VPN DNS is broken or you want to keep local DNS resolution.
# The system will use the DNS from your primary connection instead.

WireGuard handles routing differently than OpenVPN. The AllowedIPs directive in the config controls both encryption scope and routing. NetworkManager reads AllowedIPs and sets up the kernel routes accordingly. If your provider sends AllowedIPs = 0.0.0.0/0, all traffic routes through the tunnel. If they send a specific subnet, only that traffic tunnels. You rarely need to tweak routes for WireGuard. The config file drives the behavior.

Commit the route change and reconnect. The routing table updates instantly.

Common pitfalls

The error Error: Connection '...' not found usually means the import created a different name than you expect. Run nmcli connection show to see the actual profile names. Case sensitivity matters. If the name contains spaces, wrap it in quotes.

If you see Failed to activate connection, check the logs. NetworkManager might be waiting for credentials or failing to reach the server.

journalctl -u NetworkManager -xe
# The -x flag adds explanatory text. The -e flag jumps to the end.
# Look for lines mentioning the VPN plugin or authentication failures.
# SELinux denials appear here if the plugin is blocked by policy.

Credentials are stored in the system keyring. If your password changes, update the profile. You can use nmcli connection modify to set a new password, or use the interactive editor. The keyring protects the secret from plaintext exposure in config files.

nmcli connection modify "VPN Profile" 802-1x.password "newpassword"
# Updates the password stored in the keyring.
# The change takes effect on the next connection attempt.
# Do not commit the password to version control or share the profile file.

Note: Firewall rules apply only if you are running a VPN server on this machine. Clients do not need to open ports for outbound connections. If you are hosting a server, use firewall-cmd --permanent --add-port=51820/udp for WireGuard or --add-port=1194/udp for OpenVPN, then run firewall-cmd --reload.

Run journalctl -u NetworkManager -xe first. Read the actual error before guessing.

When to use this approach

Use the GUI when you are on a desktop and want quick toggling from the system tray. Use nmcli when you are on a headless server or scripting the connection. Use nmcli connection import when you have a config file from a provider. Use nmcli connection edit when you need to adjust routes, DNS, or authentication details that the import did not capture. Use journalctl -u NetworkManager when the connection fails silently and you need the daemon's perspective.

Where to go next