What Makes a VPN Actually Usable on Linux

A GUI is not a feature for sysadmins. The first thing we check is whether the VPN ships a proper CLI with scriptable output, supports WireGuard natively, and integrates with systemd without requiring a separate daemon babysitter. We also check whether the kill switch survives a `systemctl restart NetworkManager` and whether DNS reverts to the system resolver on disconnect.

The second filter is package format. AppImage-only distributions fail immediately. We need .deb, .rpm, or at minimum a clean install script that does not pipe curl into bash without a checksum. Repository-based installs that survive `apt upgrade` without breaking are the baseline.

Third: split tunneling. On a server routing traffic for multiple services, you cannot send all packets through the tunnel. Anything that lacks per-application or per-route exclusions is a no-go for production use.

Fourth: DNS leak behavior. We test this by running `tcpdump -i any port 53` during connection, during a simulated link drop, and immediately after disconnect. Several clients we tested sent DNS queries outside the tunnel during reconnection windows of 2-8 seconds.

# Verify DNS is not leaking during reconnect
sudo tcpdump -i any -n port 53 2>/dev/null | grep -v '10\.64\.'

NordVPN: Best Overall Linux VPN for 2025

NordVPN ships a native Linux CLI client - nordvpn - as a .deb and .rpm with a maintained apt/yum repository. Version 3.18.x (current as of early 2026) added meshnet routing improvements and fixed the systemd-resolved conflict that plagued 3.16.x installs on Ubuntu 24.04. Installation takes under two minutes and survives dist-upgrades cleanly.

The CLI is the strongest of any commercial VPN we tested. You get tab completion, machine-readable status output via `nordvpn status --format json` (undocumented but functional), and direct WireGuard or OpenVPN protocol selection per connection. NordLynx, their WireGuard implementation, consistently delivered the lowest latency overhead in our tests: 4-7ms added RTT on a 1Gbps server versus 18-24ms with OpenVPN on the same endpoint.

Kill switch behavior is correct. We tested by running `sudo iptables -L` before and after enabling it - NordVPN inserts its own chain (NORDVPN-INPUT, NORDVPN-OUTPUT, NORDVPN-FORWARD) and drops non-tunnel traffic without relying on ufw. The chain persists after `systemctl restart nordvpnd`, which is the failure mode we see in most competitors.

Split tunneling works at the application level via `nordvpn whitelist add subnet` and `nordvpn whitelist add port`. It does not yet support per-process exclusions on Linux the way it does on Windows, but subnet and port whitelisting covers most production cases.

The one gap: meshnet (peer-to-peer routing between your own devices) requires the nordvpnd daemon running on both ends and does not support routing arbitrary subnets behind a peer without manual iptables work. For simple site-to-site use, WireGuard directly is faster to configure. For securing individual admin workstations connecting to a shared jump box, meshnet is genuinely useful.

# Install NordVPN on Debian/Ubuntu
sh <(curl -sSf https://downloads.nordcdn.com/apps/linux/install.sh)
# Verify checksum manually first:
curl -sSf https://downloads.nordcdn.com/apps/linux/install.sh | sha256sum

# Connect with NordLynx (WireGuard)
nordvpn set technology nordlynx
nordvpn connect --group p2p us

# Enable kill switch
nordvpn set killswitch on
nordvpn set dns 103.86.96.100 103.86.99.100

# Check iptables chain is active
sudo iptables -L | grep -i nordvpn

Mullvad: Best for Privacy-First and Headless Server Use

Mullvad does not require an email address to sign up. You get a 16-digit account number and that is your entire identity with them. For threat models involving metadata, this matters. Their Linux CLI - mullvad - is open source (GPL-3.0), packaged as .deb and .rpm, and the daemon is written in Rust.

On headless servers, Mullvad's relay selection is scriptable. You can constrain to WireGuard-only endpoints in specific countries and pipe the output into monitoring scripts. Their DNS blocking feature (malware, ads, tracking categories) is applied at the VPN DNS level, which is useful for egress filtering on servers that do not warrant a full Pi-hole setup.

We measured 5-9ms overhead with WireGuard on Mullvad versus 4-7ms on NordLynx. The difference is negligible for most workloads. Where Mullvad loses ground is pricing - it is 5 EUR/month with no annual discount, which adds up for teams running multiple server VPNs. There is no meshnet equivalent, and split tunneling is supported but limited compared to NordVPN's implementation.

Multihop (chaining through two servers) works cleanly on Linux and is exposed via CLI: `mullvad relay set tunnel wireguard --use-multihop on`. We verified this adds approximately 15-20ms additional RTT and does not break the kill switch.

# Mullvad relay constrained to WireGuard US endpoints
mullvad relay set location us
mullvad relay set tunnel-protocol wireguard
mullvad connect

# Verify no DNS leaks
mullvad dns get
dig +short myip.opendns.com @resolver1.opendns.com
// advertisement

ProtonVPN: Best Free Tier and Best for Remote Teams

ProtonVPN's Linux CLI (proton-vpn-gtk-app or the older protonvpn-cli) supports headless mode. The CLI-only path is through protonvpn-cli, which is Python-based and available in the official repos. On Arch it is in the AUR (protonvpn-cli); on Debian it requires adding their repository. The free tier is legitimate: no bandwidth cap, no ads, limited to three server locations (US, Netherlands, Japan).

For teams, Proton's organizational account structure maps better to enterprise workflows than NordVPN's Teams product. You can assign users, revoke credentials, and enforce server group restrictions via the admin panel. This is less relevant for solo sysadmins but meaningful if you're standardizing VPN access across a team of five or more.

The native GUI client (proton-vpn-gtk-app) added port forwarding support in 2024, useful for hosting services behind NAT. On the CLI, port forwarding is not yet exposed. Stealth protocol (obfuscated TCP disguised as HTTPS) is available on Proton and works on restrictive networks, but requires the GUI or specific manual OpenVPN config downloads from the dashboard.

In our DNS leak tests, ProtonVPN's CLI held clean across all 12 reconnection attempts. The kill switch (`protonvpn-cli killswitch --on`) uses nftables rather than iptables on systems where nftables is the default, which is correct behavior for modern Debian and RHEL installs.

# Install protonvpn-cli on Debian 12
wget https://repo.protonvpn.com/debian/dists/stable/main/binary-all/protonvpn-stable-release_1.0.3-3_all.deb
sudo dpkg -i ./protonvpn-stable-release_1.0.3-3_all.deb
sudo apt update && sudo apt install protonvpn-cli

# Connect to fastest server
protonvpn-cli connect --fastest

# Enable kill switch permanently
protonvpn-cli killswitch --on --always-on

ExpressVPN and Surfshark: Where They Fall Short on Linux

ExpressVPN's Linux client is CLI-only, which sounds good until you use it. There is no WireGuard support on Linux as of Q1 2026 - they use their proprietary Lightway protocol (based on wolfSSL) or OpenVPN. Lightway performs well but the lack of WireGuard means you cannot inspect the tunnel interface directly with `wg show`, which matters for debugging and monitoring.

Surfshark ships a CLI with WireGuard support. The kill switch implementation, however, failed our reconnection test on Arch Linux - after `systemctl restart NetworkManager`, traffic was routed outside the tunnel for 4-6 seconds before the kill switch re-engaged. We reproduced this three times. On Debian 12 it performed correctly. If you run Arch or derivatives, treat this as a known issue until Surfshark patches their daemon.

Both products have 24/7 support, which is relevant when their clients break after a kernel update. In practice, we found NordVPN's support more technically literate for Linux-specific issues. The forum threads on Surfshark's subreddit for kill switch failures on non-Ubuntu distros are long and largely unresolved.

# Check if kill switch survived NetworkManager restart
# Run this BEFORE restarting NM, capture the output, compare after
ip route show table main | grep -v 'nordvpn\|wg0\|tun0'
sudo systemctl restart NetworkManager
sleep 2
ip route show table main | grep -v 'nordvpn\|wg0\|tun0'

Raw WireGuard vs Commercial VPN: When to Use Each

If you control both endpoints - your workstation and your server - raw WireGuard is faster to set up than any commercial VPN and has zero recurring cost. The full setup is 12 commands. If you need to connect to infrastructure you do not own, rotate exit IPs, or need obfuscation for restrictive networks, a commercial client earns its subscription fee.

For DevOps pipelines, the pattern we use is raw WireGuard between your CI runner and production environment, with a commercial VPN (NordVPN in our case) on the workstation that accesses that CI runner. This separates authentication concerns. The WireGuard tunnel is locked to a specific public key; the commercial VPN handles the variable-IP problem of remote work.

If you are automating VPN connections as part of a deployment or testing workflow, NordVPN's CLI is scriptable enough to integrate into CI steps. Commands exit with meaningful codes, `nordvpn connect` blocks until connected or fails, and you can test connectivity deterministically. For teams using AI-driven DevOps tooling, platforms like taskbotshub.ai can wrap these CLI calls into automated runbooks that handle VPN bring-up as a pre-step before deployment verification.

One caveat: never store VPN credentials in plaintext in a CI config. Use the environment variable approach with a service account token, or pre-authenticate the runner image and rotate the token on a schedule.

# Minimal WireGuard setup - server side
sudo wg genkey | tee server_private.key | wg pubkey > server_public.key
cat <
// advertisement

Testing Methodology and Performance Numbers

We tested each VPN on three machines: a Hetzner CX21 VPS running Debian 12 (headless, 2 vCPU, 4GB RAM), a local workstation running Arch Linux with kernel 6.8.9, and a RHEL 9.3 VM on VMware. Performance numbers are RTT overhead above baseline, measured with 1000 ICMP pings to 1.1.1.1 averaged over three runs.

NordLynx (NordVPN/WireGuard): 4.2ms average overhead. OpenVPN on NordVPN: 21.8ms. Mullvad WireGuard: 6.1ms. ProtonVPN WireGuard: 7.4ms. Surfshark WireGuard (Debian only): 6.8ms. ExpressVPN Lightway: 11.3ms.

DNS leak tests used bash-ipleak.net API and manual tcpdump capture. NordVPN, Mullvad, and ProtonVPN passed all 12 reconnection scenarios. Surfshark passed 10/12 (failed on Arch NetworkManager restart as noted). ExpressVPN passed 12/12 but we note the lack of WireGuard as a separate concern.

Installation success across all three distros without manual dependency resolution: NordVPN (3/3), Mullvad (3/3), ProtonVPN (2/3 - Arch AUR build failed once on a fresh install due to a Python dependency conflict, resolved on retry), ExpressVPN (3/3), Surfshark (3/3).

For teams also managing naming and branding for internal tools or projects, a clean .org or .io domain for your internal VPN documentation is worth grabbing early. Services like nicename.me make it fast to check availability across TLDs if you're setting up a named internal gateway.

# Measure VPN overhead accurately
# Run before connecting:
ping -c 1000 -q 1.1.1.1 | tail -1

# Connect VPN, then run again:
nordvpn connect
ping -c 1000 -q 1.1.1.1 | tail -1

# Output format: rtt min/avg/max/mdev = X/X/X/X ms
# Subtract baseline avg from tunnel avg for overhead

Pricing, Licensing, and Multi-Device Reality

NordVPN at the 2-year rate is approximately 3.09 USD/month and covers 6 simultaneous connections. For a sysadmin running VPN on a workstation, a home lab server, and a travel laptop, this is sufficient. NordVPN Teams pricing starts at 7 USD/user/month and adds centralized billing and user management.

Mullvad is 5 EUR/month flat with no multi-year discount and allows 5 simultaneous connections. No trials, no free tier. You buy a month, test it, continue if it works. For single-sysadmin use this is honest and simple. For teams it scales poorly.

ProtonVPN free tier is legitimate for a single device with reduced server selection. The Plus plan at 9.99 USD/month (or 4.99/month annually) includes all servers, port forwarding, and Stealth protocol. If you already use ProtonMail, the bundle discount brings VPN cost down to roughly 2 USD/month equivalent.

ExpressVPN is the most expensive at approximately 6.67 USD/month annual. Given the WireGuard gap on Linux, we do not recommend it for technical users in 2025-2026 unless Lightway's performance specifically meets a need WireGuard cannot (primarily obfuscation on deep-packet-inspection networks).

# Automate NordVPN connection with systemd on a headless server
cat <