Remote access to your self-hosted services is essential. Whether you’re checking on your media server from a coffee shop or managing your homelab while traveling, a VPN creates a secure tunnel back to your network.
But which VPN should you run? The three dominant options — WireGuard, OpenVPN, and Tailscale — take very different approaches. This guide compares all three so you can make the right choice for your setup.
Quick Comparison
| Feature | WireGuard | OpenVPN | Tailscale |
|---|---|---|---|
| Protocol | WireGuard | OpenVPN (custom) | WireGuard (underneath) |
| Speed | ⚡ Fastest | Moderate | Fast |
| Setup difficulty | Medium | Hard | Very easy |
| Config style | CLI / config files | Config files + PKI | Web dashboard + CLI |
| Code size | ~4,000 lines | ~100,000+ lines | Proprietary control plane |
| NAT traversal | Manual port forward | Manual port forward | Automatic |
| Self-hosted control | Full | Full | Partial (Headscale for full) |
| Mobile apps | ✅ Official | ✅ Official | ✅ Official |
| Peer-to-peer | ❌ Client-server | ❌ Client-server | ✅ Mesh network |
WireGuard: The Speed King
WireGuard is a modern VPN protocol built into the Linux kernel since version 5.6. It’s fast, lightweight, and uses state-of-the-art cryptography with zero configuration choices — there’s one cipher suite, and it’s a good one.
Why Choose WireGuard
- Raw performance — kernel-level implementation means minimal overhead
- Tiny attack surface — roughly 4,000 lines of code vs 100,000+ for OpenVPN
- Simple configuration — each peer gets a public/private key pair
- Roaming support — seamlessly switches between WiFi and cellular
- Low latency — 1-RTT handshake vs OpenVPN’s multi-step process
Docker Setup with wg-easy
The easiest way to run WireGuard is with the wg-easy Docker image, which adds a web UI:
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:latest
container_name: wg-easy
restart: unless-stopped
environment:
- LANG=en
- WG_HOST=vpn.yourdomain.com
- PASSWORD_HASH=$$2y$$10$$yourbcrypthashhere
- WG_DEFAULT_DNS=1.1.1.1,9.9.9.9
- WG_ALLOWED_IPS=0.0.0.0/0
ports:
- "51820:51820/udp"
- "51821:51821/tcp" # Web UI
volumes:
- ./wireguard:/etc/wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
Generate the password hash first:
docker run -it ghcr.io/wg-easy/wg-easy wgpw 'YOUR_PASSWORD'
Deploy and access the web UI at http://your-server:51821. From there, create clients with one click and scan QR codes on your phone.
Manual WireGuard Setup
For more control, configure WireGuard directly:
# Install
sudo apt install wireguard
# Generate keys
wg genkey | tee server_private.key | wg pubkey > server_public.key
wg genkey | tee client_private.key | wg pubkey > client_public.key
Server config (/etc/wireguard/wg0.conf):
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server_private_key>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = <client_public_key>
AllowedIPs = 10.0.0.2/32
Client config:
[Interface]
Address = 10.0.0.2/24
PrivateKey = <client_private_key>
DNS = 1.1.1.1
[Peer]
PublicKey = <server_public_key>
Endpoint = vpn.yourdomain.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
WireGuard Pros and Cons
Pros:
- Fastest VPN option available
- Minimal resource usage
- Built into Linux kernel
- Simple, auditable codebase
- Excellent mobile apps
Cons:
- Requires a public IP or port forwarding
- No built-in user authentication (key-based only)
- No dynamic IP handling without extra tools
- Each peer must be manually configured (without a UI wrapper)
OpenVPN: The Battle-Tested Veteran
OpenVPN has been the go-to self-hosted VPN for over two decades. It’s mature, flexible, and runs on virtually every platform. While newer options outperform it, OpenVPN’s ecosystem and configurability remain unmatched.
Why Choose OpenVPN
- Maximum compatibility — works on any OS, even older devices
- Flexible authentication — certificates, username/password, LDAP, RADIUS
- TCP fallback — can run over TCP port 443 to bypass restrictive firewalls
- Proven security — decades of security audits and hardening
- Rich plugin ecosystem — extensive customization options
Docker Setup with OpenVPN Access Server
services:
openvpn:
image: openvpn/openvpn-as
container_name: openvpn-as
restart: unless-stopped
ports:
- "943:943" # Web UI
- "443:443" # VPN (TCP)
- "1194:1194/udp" # VPN (UDP)
volumes:
- ./openvpn-data:/openvpn
cap_add:
- NET_ADMIN
Or use the community edition with kylemanna/openvpn:
services:
openvpn:
image: kylemanna/openvpn
container_name: openvpn
restart: unless-stopped
ports:
- "1194:1194/udp"
volumes:
- ./openvpn-data:/etc/openvpn
cap_add:
- NET_ADMIN
Initial setup requires generating the PKI infrastructure:
# Initialize config
docker run -v ./openvpn-data:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.yourdomain.com
# Generate certificates (you'll set a CA password)
docker run -v ./openvpn-data:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki
# Create a client certificate
docker run -v ./openvpn-data:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full client1 nopass
# Export client config
docker run -v ./openvpn-data:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient client1 > client1.ovpn
OpenVPN Pros and Cons
Pros:
- Runs everywhere — Windows, macOS, Linux, iOS, Android, routers
- TCP mode punches through corporate firewalls
- Certificate-based authentication is enterprise-grade
- Can push routes, DNS settings, and more to clients
- Massive community and documentation
Cons:
- Significantly slower than WireGuard (userspace, not kernel)
- Complex initial setup with PKI/certificate management
- Higher CPU usage, especially on low-power devices
- Larger codebase means larger attack surface
- Configuration files can be intimidating
Tailscale: The Zero-Config Mesh
Tailscale takes WireGuard and wraps it in a coordination layer that handles all the hard parts — NAT traversal, key exchange, DNS, and access control. The result is a VPN that “just works” without port forwarding, firewall rules, or manual configuration.
Why Choose Tailscale
- Zero port forwarding — works behind NAT, CGNAT, and firewalls
- Mesh networking — devices connect directly to each other
- MagicDNS — access devices by name (e.g.,
my-server) - SSO integration — authenticate with Google, GitHub, Microsoft, etc.
- ACLs — fine-grained access control per user and device
Setup
Tailscale doesn’t need Docker (though it supports it). Install directly:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
That’s it. Authenticate in your browser, and the device joins your tailnet. Repeat on every device you want connected.
Docker Setup (for containerized services)
If you want to expose Docker services through Tailscale:
services:
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
restart: unless-stopped
hostname: my-server
environment:
- TS_AUTHKEY=tskey-auth-xxxxx
- TS_STATE_DIR=/var/lib/tailscale
- TS_EXTRA_ARGS=--advertise-exit-node --advertise-routes=192.168.1.0/24
volumes:
- ./tailscale-state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
- NET_RAW
network_mode: host
Subnet Routing
Tailscale can advertise your entire home network so you can access any device — not just those running Tailscale:
sudo tailscale up --advertise-routes=192.168.1.0/24
Approve the route in the Tailscale admin console, and every device on your tailnet can reach your home network.
Exit Nodes
Use any Tailscale device as a VPN exit point:
# On the server
sudo tailscale up --advertise-exit-node
# On the client
sudo tailscale up --exit-node=my-server
All your traffic now routes through your home server — useful for privacy on public WiFi.
The Self-Hosting Concern
Tailscale’s control plane is hosted by Tailscale Inc. Your traffic is encrypted end-to-end and never passes through their servers, but they handle coordination, key distribution, and NAT traversal.
If this concerns you, Headscale is an open-source, self-hosted implementation of the Tailscale control server:
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
restart: unless-stopped
ports:
- "8080:8080"
- "9090:9090"
volumes:
- ./headscale-config:/etc/headscale
- ./headscale-data:/var/lib/headscale
command: serve
With Headscale, you get Tailscale’s ease of use with full self-hosted control. Check out our Headscale setup guide for details.
Tailscale Pros and Cons
Pros:
- Easiest setup of any VPN — period
- No port forwarding required
- Direct peer-to-peer connections (fast)
- MagicDNS and HTTPS certificates built in
- Generous free tier (100 devices, 3 users)
Cons:
- Control plane is not self-hosted (unless using Headscale)
- Free tier has user limits
- Paid plans required for larger teams
- Less control over low-level networking
- Dependency on third-party service for coordination
Performance Benchmarks
Real-world throughput on a typical homelab setup (Gigabit LAN, modern hardware):
| VPN | Download | Upload | Latency Overhead |
|---|---|---|---|
| No VPN (baseline) | 940 Mbps | 940 Mbps | 0 ms |
| WireGuard | 880 Mbps | 850 Mbps | +0.5 ms |
| Tailscale (direct) | 850 Mbps | 820 Mbps | +0.8 ms |
| OpenVPN (UDP) | 450 Mbps | 400 Mbps | +2 ms |
| OpenVPN (TCP) | 300 Mbps | 280 Mbps | +5 ms |
WireGuard and Tailscale (which uses WireGuard underneath) are significantly faster than OpenVPN. On low-power devices like a Raspberry Pi, the difference is even more dramatic.
Security Comparison
Cryptography
- WireGuard: ChaCha20, Poly1305, Curve25519, BLAKE2s — modern, fast, no configuration
- OpenVPN: Configurable — AES-256-GCM recommended, but older setups may use weaker ciphers
- Tailscale: WireGuard’s crypto stack + additional authentication layer
Attack Surface
- WireGuard: ~4,000 lines of kernel code, formally verified
- OpenVPN: 100,000+ lines, long history of CVEs (though well-patched)
- Tailscale: WireGuard for data plane, proprietary coordination plane
Authentication
- WireGuard: Pre-shared public keys only
- OpenVPN: Certificates, username/password, MFA, LDAP, RADIUS
- Tailscale: SSO (Google, GitHub, Microsoft, OIDC), device authorization
Which Should You Choose?
Choose WireGuard if:
- You want maximum performance
- You have a public IP or can port forward
- You’re comfortable with CLI configuration
- You want full control with minimal dependencies
- You’re running on low-power hardware (Pi, NAS)
Choose OpenVPN if:
- You need to work behind restrictive corporate firewalls (TCP/443)
- You require certificate-based enterprise authentication
- You need compatibility with older devices or routers
- You want the most battle-tested, audited option
- Your organization mandates OpenVPN compliance
Choose Tailscale if:
- You want the easiest possible setup
- You’re behind CGNAT or can’t port forward
- You need to connect devices across multiple locations
- You want mesh networking (device-to-device)
- You don’t mind a hosted control plane (or will use Headscale)
Our Recommendation
For most self-hosters: start with Tailscale.
It solves the hardest problem — NAT traversal — without any configuration. You’ll be connected in under five minutes. If you later want full self-hosted control, migrate to Headscale with minimal effort.
For performance-critical use cases, run WireGuard with wg-easy for the web UI. It’s the fastest option and gives you complete control.
Use OpenVPN only if you specifically need TCP tunneling through restrictive firewalls or enterprise-grade certificate authentication. For everything else, WireGuard-based solutions are simply better in 2026.
Can You Run Multiple?
Absolutely. Many self-hosters run Tailscale for everyday remote access and WireGuard for site-to-site tunnels or specific high-throughput needs. They use different ports and don’t conflict.
Conclusion
The VPN landscape has shifted dramatically. WireGuard’s inclusion in the Linux kernel and Tailscale’s zero-config approach have made self-hosted VPNs accessible to everyone. OpenVPN still has its place, but for new setups, WireGuard-based solutions offer better performance, simpler configuration, and stronger security with less code.
Pick one, set it up, and never worry about accessing your homelab from anywhere again.