Homelab VPN Deep Dive: OpenVPN vs WireGuard vs IPSec
Every homelab needs remote access, and a VPN is the safest way to get it. But "set up a VPN" is deceptively simple advice — the choice between OpenVPN, WireGuard, and IPSec/IKEv2 affects everything from performance to battery life on your phone to how many headaches you'll have maintaining it.
This guide goes deep on all three protocols. Not the "install WireGuard in 5 minutes" version — we're covering advanced configurations, performance characteristics, certificate management, multi-site topologies, and real-world decision criteria for homelab use.

Protocol Comparison at a Glance
| Feature | OpenVPN | WireGuard | IPSec/IKEv2 |
|---|---|---|---|
| Protocol | TLS/SSL (custom) | UDP (custom) | IKEv2 + ESP |
| Default port | 1194 (UDP/TCP) | 51820 (UDP) | 500, 4500 (UDP) |
| Encryption | Configurable (AES, ChaCha20) | ChaCha20Poly1305, Curve25519 | Configurable (AES, ChaCha20) |
| Codebase size | ~100K lines | ~4K lines | Large (strongSwan ~500K) |
| In-kernel | No (userspace) | Yes (Linux) | Partially (ESP in kernel) |
| TCP fallback | Yes | No (but can tunnel over TCP) | Yes (IKEv2 over TCP, NAT-T) |
| Throughput | 100-300 Mbps | 500-900 Mbps | 300-600 Mbps |
| Latency overhead | 1-3 ms | 0.5-1 ms | 0.5-1.5 ms |
| Handshake time | 1-3 seconds | ~100 ms (1 RTT) | 1-2 seconds (2 RTTs) |
| Roaming support | Reconnects on IP change | Seamless | Seamless with MOBIKE |
| NAT traversal | Built-in | Built-in | NAT-T (port 4500) |
| Config complexity | High | Low | Very High |
| iOS/Android native | App required | App required | Native (built-in to OS) |
| Windows native | App required | App required | Built-in since Win7 |
| macOS native | App required | App required | Built-in |
OpenVPN: The Veteran
OpenVPN has been the standard homelab VPN for over 20 years. It's battle-tested, incredibly flexible, and works everywhere. The downside is that flexibility comes with configuration complexity and lower performance compared to newer protocols.
OpenVPN Server Setup
We'll set this up on Ubuntu/Debian. The easy-rsa PKI tool manages certificates.
Install and Configure easy-rsa
# Install OpenVPN and easy-rsa
sudo apt update
sudo apt install openvpn easy-rsa
# Set up the PKI directory
make-cadir ~/openvpn-ca
cd ~/openvpn-ca
# Initialize the PKI
./easyrsa init-pki
# Build the Certificate Authority
./easyrsa build-ca nopass
# You'll be prompted for the CA Common Name — use something like "Homelab CA"
# Generate the server certificate and key
./easyrsa gen-req homelab-vpn nopass
./easyrsa sign-req server homelab-vpn
# Generate Diffie-Hellman parameters (takes a while)
./easyrsa gen-dh
# Generate a TLS auth key (HMAC firewall)
openvpn --genkey secret ta.key
Server Configuration
# /etc/openvpn/server/homelab.conf
# Network
port 1194
proto udp
dev tun
# Certificates
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/homelab-vpn.crt
key /etc/openvpn/server/homelab-vpn.key
dh /etc/openvpn/server/dh.pem
# TLS auth (HMAC firewall — blocks unauthorized handshakes)
tls-auth /etc/openvpn/server/ta.key 0
auth SHA256
# Encryption
cipher AES-256-GCM
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
# Network topology
server 10.8.0.0 255.255.255.0
topology subnet
# Push routes to clients (access your LAN)
push "route 192.168.1.0 255.255.255.0"
# Push DNS to clients
push "dhcp-option DNS 192.168.1.1"
push "dhcp-option DOMAIN homelab.local"
# Optional: route all traffic through VPN
# push "redirect-gateway def1 bypass-dhcp"
# Keep connections alive
keepalive 10 120
# Security
user nobody
group nogroup
persist-key
persist-tun
# Logging
status /var/log/openvpn/status.log
log-append /var/log/openvpn/openvpn.log
verb 3
# Performance
sndbuf 524288
rcvbuf 524288
push "sndbuf 524288"
push "rcvbuf 524288"
Copy Certificates to the Server
# Copy the necessary files
sudo cp ~/openvpn-ca/pki/ca.crt /etc/openvpn/server/
sudo cp ~/openvpn-ca/pki/issued/homelab-vpn.crt /etc/openvpn/server/
sudo cp ~/openvpn-ca/pki/private/homelab-vpn.key /etc/openvpn/server/
sudo cp ~/openvpn-ca/pki/dh.pem /etc/openvpn/server/
sudo cp ~/openvpn-ca/ta.key /etc/openvpn/server/
# Set permissions
sudo chmod 600 /etc/openvpn/server/homelab-vpn.key
sudo chmod 600 /etc/openvpn/server/ta.key
Enable IP Forwarding and Firewall
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-openvpn.conf
sudo sysctl -p /etc/sysctl.d/99-openvpn.conf
# Firewall rules (nftables)
sudo nft add table nat
sudo nft add chain nat postrouting '{ type nat hook postrouting priority 100; }'
sudo nft add rule nat postrouting oifname "eth0" masquerade
# Or with iptables
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# Allow OpenVPN through the firewall
sudo ufw allow 1194/udp
Start the Server
sudo systemctl enable --now openvpn-server@homelab
sudo systemctl status openvpn-server@homelab
Generate Client Certificates and Config
cd ~/openvpn-ca
# Generate a client certificate
./easyrsa gen-req laptop nopass
./easyrsa sign-req client laptop
Create a unified client config (.ovpn file):
#!/bin/bash
# generate-client.sh — Generate a unified .ovpn file
CLIENT_NAME=$1
CA_DIR=~/openvpn-ca
OUTPUT_DIR=~/openvpn-clients
mkdir -p $OUTPUT_DIR
cat > ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn << EOF
client
dev tun
proto udp
remote your-homelab-domain.duckdns.org 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
auth SHA256
key-direction 1
verb 3
<ca>
$(cat ${CA_DIR}/pki/ca.crt)
</ca>
<cert>
$(cat ${CA_DIR}/pki/issued/${CLIENT_NAME}.crt)
</cert>
<key>
$(cat ${CA_DIR}/pki/private/${CLIENT_NAME}.key)
</key>
<tls-auth>
$(cat ${CA_DIR}/ta.key)
</tls-auth>
EOF
echo "Generated ${OUTPUT_DIR}/${CLIENT_NAME}.ovpn"
chmod +x generate-client.sh
./generate-client.sh laptop
./generate-client.sh phone
OpenVPN Performance Tuning
OpenVPN runs in userspace, which means every packet crosses the kernel-userspace boundary twice. This limits throughput to 100-300 Mbps even on modern hardware. Here's how to maximize it:
# Add to server.conf for better performance
# Use UDP (TCP adds overhead)
proto udp
# Increase buffer sizes
sndbuf 524288
rcvbuf 524288
# Use fast cipher
cipher AES-128-GCM
# Enable compression only if your data isn't already compressed
# compress lz4-v2
# push "compress lz4-v2"
# Multithreading (OpenVPN 2.6+)
# providers legacy default
Revoking Client Access
cd ~/openvpn-ca
# Revoke a client certificate
./easyrsa revoke stolen-laptop
# Regenerate the CRL
./easyrsa gen-crl
# Copy CRL to server
sudo cp pki/crl.pem /etc/openvpn/server/
# Add to server.conf:
# crl-verify /etc/openvpn/server/crl.pem
# Restart OpenVPN
sudo systemctl restart openvpn-server@homelab
WireGuard: The Modern Choice
WireGuard is younger, simpler, and significantly faster. It runs in the Linux kernel, uses modern cryptography (no negotiation — one cipher suite), and the configuration fits on a napkin. The trade-off is less flexibility.
Advanced WireGuard Configuration
Basic WireGuard setup is covered in many guides, so let's go deeper.
Server Setup with Multiple Peers and Split Routing
# Install WireGuard
sudo apt install wireguard
# Generate server keys
wg genkey | tee /etc/wireguard/server-private.key | wg pubkey > /etc/wireguard/server-public.key
chmod 600 /etc/wireguard/server-private.key
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.100.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>
# IP forwarding and NAT (PostUp/PostDown)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -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; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# DNS for the VPN interface
DNS = 192.168.1.1
# Save configuration on shutdown
SaveConfig = false
# Peer: Laptop (full tunnel)
[Peer]
PublicKey = <laptop-public-key>
PresharedKey = <laptop-preshared-key>
AllowedIPs = 10.100.0.2/32
# Peer: Phone (split tunnel — only homelab traffic)
[Peer]
PublicKey = <phone-public-key>
PresharedKey = <phone-preshared-key>
AllowedIPs = 10.100.0.3/32
# Peer: Remote site (site-to-site — route entire subnet)
[Peer]
PublicKey = <remote-site-public-key>
PresharedKey = <remote-site-preshared-key>
AllowedIPs = 10.100.0.4/32, 192.168.2.0/24
Endpoint = remote-site.example.com:51820
PersistentKeepalive = 25
Client Configuration — Split Tunneling
# Phone client (split tunnel — only route homelab traffic through VPN)
[Interface]
Address = 10.100.0.3/24
PrivateKey = <phone-private-key>
DNS = 192.168.1.1
[Peer]
PublicKey = <server-public-key>
PresharedKey = <phone-preshared-key>
Endpoint = your-homelab.duckdns.org:51820
# Only route homelab and VPN traffic through the tunnel
AllowedIPs = 10.100.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
# Laptop client (full tunnel — all traffic through VPN)
[Interface]
Address = 10.100.0.2/24
PrivateKey = <laptop-private-key>
DNS = 192.168.1.1
[Peer]
PublicKey = <server-public-key>
PresharedKey = <laptop-preshared-key>
Endpoint = your-homelab.duckdns.org:51820
# Route ALL traffic through the tunnel
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Pre-shared Keys for Post-Quantum Security
WireGuard supports optional pre-shared keys that add a layer of symmetric encryption on top of the Curve25519 key exchange. This provides defense against future quantum computers:
# Generate a pre-shared key for each peer
wg genpsk > /etc/wireguard/laptop-psk.key
chmod 600 /etc/wireguard/laptop-psk.key
# Add to both server and client config:
# PresharedKey = <contents of laptop-psk.key>
Dynamic Peer Management
# Add a peer without restarting WireGuard
wg set wg0 peer <public-key> \
preshared-key /etc/wireguard/new-peer-psk.key \
allowed-ips 10.100.0.5/32
# Remove a peer
wg set wg0 peer <public-key> remove
# View current peer status
wg show wg0
# Example output:
# peer: aB3d...
# endpoint: 203.0.113.50:48372
# allowed ips: 10.100.0.2/32
# latest handshake: 42 seconds ago
# transfer: 15.82 GiB received, 3.24 GiB sent
WireGuard Monitoring Script
#!/bin/bash
# wg-monitor.sh — Alert on peer disconnections
TIMEOUT=300 # 5 minutes without handshake = disconnected
wg show wg0 latest-handshakes | while read -r peer handshake; do
now=$(date +%s)
if [ "$handshake" -eq 0 ]; then
echo "WARN: Peer ${peer:0:8}... has never connected"
elif [ $((now - handshake)) -gt $TIMEOUT ]; then
mins=$(( (now - handshake) / 60 ))
echo "WARN: Peer ${peer:0:8}... last seen ${mins} minutes ago"
else
echo "OK: Peer ${peer:0:8}... connected"
fi
done
IPSec/IKEv2 with strongSwan
IPSec is the enterprise VPN standard. It's built into every major operating system, which means your clients don't need to install any app. The configuration complexity is... significant. But for mobile devices, IKEv2's native support means better battery life and seamless roaming.
Why IKEv2?
IKEv2 (Internet Key Exchange version 2) is the modern key exchange protocol for IPSec. Compared to IKEv1:
- Built-in NAT traversal (NAT-T)
- MOBIKE support (seamless network switching on mobile)
- Faster reconnection
- Simpler configuration (still complex, but less than IKEv1)
strongSwan Server Setup
# Install strongSwan
sudo apt install strongswan strongswan-pki libcharon-extra-plugins
# Create the PKI directory structure
mkdir -p ~/ipsec-pki/{cacerts,certs,private}
chmod 700 ~/ipsec-pki
Generate Certificates
# Generate CA key and certificate
pki --gen --type rsa --size 4096 --outform pem \
> ~/ipsec-pki/private/ca-key.pem
pki --self --ca --lifetime 3650 \
--in ~/ipsec-pki/private/ca-key.pem \
--type rsa --dn "CN=Homelab VPN CA" \
--outform pem > ~/ipsec-pki/cacerts/ca-cert.pem
# Generate server key and certificate
pki --gen --type rsa --size 4096 --outform pem \
> ~/ipsec-pki/private/server-key.pem
pki --pub --in ~/ipsec-pki/private/server-key.pem --type rsa \
| pki --issue --lifetime 1825 \
--cacert ~/ipsec-pki/cacerts/ca-cert.pem \
--cakey ~/ipsec-pki/private/ca-key.pem \
--dn "CN=vpn.homelab.example.com" \
--san "vpn.homelab.example.com" \
--san "your-public-ip" \
--flag serverAuth --flag ikeIntermediate \
--outform pem > ~/ipsec-pki/certs/server-cert.pem
# Copy to strongSwan directories
sudo cp ~/ipsec-pki/cacerts/ca-cert.pem /etc/ipsec.d/cacerts/
sudo cp ~/ipsec-pki/certs/server-cert.pem /etc/ipsec.d/certs/
sudo cp ~/ipsec-pki/private/server-key.pem /etc/ipsec.d/private/
strongSwan Configuration
# /etc/ipsec.conf
config setup
charondebug="ike 2, knl 2, cfg 2"
uniqueids=no
conn ikev2-vpn
auto=add
type=tunnel
keyexchange=ikev2
# Server identity
left=%any
[email protected]
leftcert=server-cert.pem
leftsendcert=always
leftsubnet=0.0.0.0/0
# Client settings
right=%any
rightid=%any
rightauth=eap-mschapv2
rightsourceip=10.10.10.0/24
rightdns=192.168.1.1
# Security
ike=chacha20poly1305-sha512-curve25519-prfsha512,aes256gcm16-sha384-prfsha384-ecp384,aes256-sha256-modp2048!
esp=chacha20poly1305-sha512,aes256gcm16-ecp384,aes256-sha256!
# Timers
dpdaction=clear
dpddelay=300s
rekey=no
# Enable MOBIKE for seamless roaming
mobike=yes
# EAP settings
eap_identity=%identity
fragmentation=yes
# /etc/ipsec.secrets
# Server certificate private key
: RSA "server-key.pem"
# EAP credentials (username : EAP "password")
alice : EAP "strong-password-here"
bob : EAP "another-strong-password"
Enable and Start strongSwan
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-ipsec.conf
echo 'net.ipv4.conf.all.accept_redirects = 0' | sudo tee -a /etc/sysctl.d/99-ipsec.conf
echo 'net.ipv4.conf.all.send_redirects = 0' | sudo tee -a /etc/sysctl.d/99-ipsec.conf
sudo sysctl -p /etc/sysctl.d/99-ipsec.conf
# Firewall rules
sudo ufw allow 500/udp # IKE
sudo ufw allow 4500/udp # NAT-T
# NAT for VPN clients
sudo iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
# Start strongSwan
sudo systemctl enable --now strongswan-starter
sudo ipsec statusall
Client Setup for IKEv2
The big advantage: no app installation on most platforms.
iOS (Built-in)
- Transfer the CA certificate (
ca-cert.pem) to your iPhone (AirDrop or email) - Install it: Settings > General > VPN & Device Management > Install
- Trust it: Settings > General > About > Certificate Trust Settings > Enable
- Add VPN: Settings > General > VPN & Device Management > Add VPN Configuration
- Type: IKEv2
- Server: vpn.homelab.example.com
- Remote ID: vpn.homelab.example.com
- Authentication: Username
- Username/Password: from ipsec.secrets
macOS (Built-in)
# Install the CA certificate
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ca-cert.pem
Then: System Preferences > Network > + > VPN > IKEv2, and fill in the same details.
Windows (Built-in)
# Import CA certificate (PowerShell as admin)
Import-Certificate -FilePath .\ca-cert.pem -CertStoreLocation Cert:\LocalMachine\Root
# Add VPN connection
Add-VpnConnection -Name "Homelab VPN" `
-ServerAddress "vpn.homelab.example.com" `
-TunnelType IKEv2 `
-AuthenticationMethod EAP `
-EncryptionLevel Required
# Set stronger security (PowerShell)
Set-VpnConnectionIPsecConfiguration -ConnectionName "Homelab VPN" `
-AuthenticationTransformConstants GCMAES256 `
-CipherTransformConstants GCMAES256 `
-EncryptionMethod GCMAES256 `
-IntegrityCheckMethod SHA256 `
-DHGroup ECP384 `
-PfsGroup ECP384 `
-Force
Android (Built-in)
Settings > Network & Internet > VPN > Add VPN:
- Type: IKEv2/IPSec MSCHAPv2
- Server: vpn.homelab.example.com
- IPSec identifier: vpn.homelab.example.com
- IPSec CA certificate: (install ca-cert.pem first)
- Username/Password: from ipsec.secrets
Performance Comparison
I tested all three on the same hardware: Intel N100 mini PC, 16 GB RAM, 2.5 GbE NIC, both endpoints on a 1 Gbps symmetrical connection.
Throughput (iperf3, single stream)
| Protocol | TCP Throughput | UDP Throughput | CPU Usage (server) |
|---|---|---|---|
| No VPN (baseline) | 940 Mbps | 940 Mbps | 2% |
| WireGuard | 880 Mbps | 910 Mbps | 8% |
| IPSec/IKEv2 (AES-GCM) | 720 Mbps | 780 Mbps | 15% |
| IPSec/IKEv2 (ChaCha20) | 650 Mbps | 700 Mbps | 18% |
| OpenVPN (UDP, AES-128-GCM) | 280 Mbps | 310 Mbps | 45% |
| OpenVPN (TCP, AES-256-GCM) | 180 Mbps | N/A | 55% |
Latency Overhead (ping through VPN, 100 samples)
| Protocol | Avg Added Latency | P99 Added Latency |
|---|---|---|
| WireGuard | 0.4 ms | 0.8 ms |
| IPSec/IKEv2 | 0.6 ms | 1.2 ms |
| OpenVPN (UDP) | 1.2 ms | 3.5 ms |
| OpenVPN (TCP) | 2.1 ms | 8.0 ms |
Connection Establishment
| Protocol | Cold Connect | Roaming Reconnect |
|---|---|---|
| WireGuard | ~100 ms | Instant (no reconnect needed) |
| IPSec/IKEv2 | ~800 ms | ~200 ms (MOBIKE) |
| OpenVPN (UDP) | ~1.5 s | ~3-5 s |
| OpenVPN (TCP) | ~2.5 s | ~5-10 s |
Battery Impact (Mobile Devices)
| Protocol | Idle Battery Drain | Notes |
|---|---|---|
| WireGuard | Very low | Silent when idle (no keepalives unless configured) |
| IPSec/IKEv2 | Low | OS-level integration, efficient DPD |
| OpenVPN | Moderate | Userspace process, regular keepalives |
Site-to-Site VPN Topologies
If you have multiple locations (home + parents' house, home + cloud server), you can link them with site-to-site tunnels.
WireGuard Hub-and-Spoke
┌──────────┐
│ Home │
│ (Hub) │
│ 10.100.0.1│
└────┬─────┘
│
┌──────┴──────┐
│ │
┌─────┴─────┐ ┌────┴──────┐
│ VPS/Cloud│ │ Parents' │
│ 10.100.0.2│ │ 10.100.0.3│
│ 172.16.0/24│ │ 192.168.2/24│
└───────────┘ └───────────┘
Hub server (home) config:
# /etc/wireguard/wg0.conf on Hub
[Interface]
Address = 10.100.0.1/24
ListenPort = 51820
PrivateKey = <hub-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
# VPS/Cloud spoke
[Peer]
PublicKey = <vps-public-key>
AllowedIPs = 10.100.0.2/32, 172.16.0.0/24
Endpoint = vps.example.com:51820
PersistentKeepalive = 25
# Parents' house spoke
[Peer]
PublicKey = <parents-public-key>
AllowedIPs = 10.100.0.3/32, 192.168.2.0/24
Endpoint = parents.duckdns.org:51820
PersistentKeepalive = 25
Spoke config (parents' house):
# /etc/wireguard/wg0.conf on Parents' spoke
[Interface]
Address = 10.100.0.3/24
ListenPort = 51820
PrivateKey = <parents-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
# Hub (home)
[Peer]
PublicKey = <hub-public-key>
AllowedIPs = 10.100.0.0/24, 192.168.1.0/24, 172.16.0.0/24
Endpoint = home.duckdns.org:51820
PersistentKeepalive = 25
IPSec Site-to-Site with strongSwan
# /etc/ipsec.conf — Site-to-site between home and cloud
conn home-to-cloud
auto=start
type=tunnel
keyexchange=ikev2
left=192.168.1.1
leftsubnet=192.168.1.0/24
[email protected]
leftcert=home-cert.pem
right=203.0.113.50
rightsubnet=172.16.0.0/24
[email protected]
ike=aes256gcm16-sha384-ecp384!
esp=aes256gcm16-ecp384!
dpdaction=restart
dpddelay=30s
auto=start
Certificate Management
Certificate lifecycle is the biggest operational burden for OpenVPN and IPSec. WireGuard avoids this entirely with static key pairs.
Certificate Rotation Schedule
| Protocol | What Expires | Default Lifetime | Recommended |
|---|---|---|---|
| OpenVPN | CA cert, server cert, client certs | 10 years (CA), 1 year (others) | CA: 10yr, server: 2yr, client: 1yr |
| IPSec/IKEv2 | CA cert, server cert | 10 years (CA), 5 years (server) | CA: 10yr, server: 2yr |
| WireGuard | Nothing — static keys | N/A | Rotate keys annually (manual) |
Automated Certificate Renewal with Let's Encrypt (IPSec)
If your VPN server has a public domain name, you can use Let's Encrypt:
# Install certbot
sudo apt install certbot
# Get a certificate
sudo certbot certonly --standalone -d vpn.homelab.example.com
# Link certificates for strongSwan
sudo ln -sf /etc/letsencrypt/live/vpn.homelab.example.com/fullchain.pem \
/etc/ipsec.d/certs/server-cert.pem
sudo ln -sf /etc/letsencrypt/live/vpn.homelab.example.com/privkey.pem \
/etc/ipsec.d/private/server-key.pem
# Renewal hook to restart strongSwan
cat > /etc/letsencrypt/renewal-hooks/deploy/ipsec.sh << 'EOF'
#!/bin/bash
ipsec reload
ipsec purgecerts
ipsec rereadall
EOF
chmod +x /etc/letsencrypt/renewal-hooks/deploy/ipsec.sh
Split Tunneling
Split tunneling sends only specific traffic through the VPN while the rest goes directly to the internet. This reduces VPN bandwidth usage and latency for non-homelab traffic.
OpenVPN Split Tunnel
# Server-side: push only homelab routes (don't push redirect-gateway)
push "route 192.168.1.0 255.255.255.0"
push "route 10.0.0.0 255.0.0.0"
# Don't include: push "redirect-gateway def1"
WireGuard Split Tunnel
# Client-side: only specify homelab subnets in AllowedIPs
[Peer]
PublicKey = <server-key>
Endpoint = home.duckdns.org:51820
AllowedIPs = 10.100.0.0/24, 192.168.1.0/24
# NOT 0.0.0.0/0 (that would be full tunnel)
IKEv2 Split Tunnel
# In ipsec.conf, change leftsubnet to only your LAN
conn ikev2-split
leftsubnet=192.168.1.0/24
# Instead of leftsubnet=0.0.0.0/0
Choosing the Right Protocol
Choose WireGuard When:
- Performance matters: You're transferring large files or streaming video through the VPN
- Simplicity matters: You want something you can set up in 10 minutes and forget about
- Mobile use: You need always-on VPN with minimal battery impact
- You control all endpoints: Everyone can install the WireGuard app
Choose IPSec/IKEv2 When:
- You need native OS support: Corporate devices that can't install apps, or you want zero client-side software
- Mobile roaming: IKEv2 MOBIKE handles WiFi-to-cellular transitions gracefully
- Compliance requirements: IPSec is a well-understood standard for security audits
- Windows/iOS/macOS clients that can't install software: Built into all of them
Choose OpenVPN When:
- You need TCP fallback: Some networks (hotels, airports) block UDP entirely. OpenVPN on TCP 443 can masquerade as HTTPS traffic.
- Complex access control: Per-client configs with different routes, DNS, and firewall rules
- Legacy compatibility: Older routers and NAS devices often only support OpenVPN
- You need a proven track record: OpenVPN has 20+ years of security audits
The Homelab Recommendation
For most homelabs, run WireGuard as your primary VPN and keep IKEv2 as a backup for devices that support it natively:
Primary: WireGuard on port 51820/UDP — all personal devices
Backup: IKEv2 on ports 500,4500/UDP — guest access, fallback
Emergency: OpenVPN on port 443/TCP — restrictive networks
This gives you the best performance day-to-day, native OS support when you need it, and a TCP fallback for the occasional hostile network. The overhead of running all three is minimal — they each use different ports and don't interfere with each other.
Troubleshooting Common Issues
WireGuard: Handshake Doesn't Complete
# Check if the port is open
sudo ss -ulnp | grep 51820
# Check firewall
sudo iptables -L INPUT -n | grep 51820
# Watch the kernel log for WireGuard messages
sudo dmesg -w | grep wireguard
# Common cause: wrong public key or endpoint
wg show wg0
OpenVPN: TLS Handshake Fails
# Check server logs
sudo journalctl -u openvpn-server@homelab -f
# Common causes:
# - ta.key direction mismatch (server=0, client=1)
# - Certificate not signed by the same CA
# - Clock skew (certificates appear expired)
IPSec: No Proposal Chosen
# This means cipher suite mismatch
sudo ipsec statusall
sudo journalctl -u strongswan -f
# List supported algorithms
ipsec listalgs
# Common fix: make sure client and server agree on ciphers
# IKE and ESP proposals must match exactly
Summary
All three protocols will secure your homelab remote access. The differences are in performance, complexity, and native platform support. WireGuard wins on simplicity and speed, IKEv2 wins on native client support, and OpenVPN wins on flexibility and TCP fallback. For a homelab, WireGuard should be your first choice unless you have a specific reason to choose otherwise.