VPN vs Reverse Proxy: Secure Remote Access to Your Homelab
When I first ran services on my homelab—Nextcloud, Jellyfin, Vaultwarden—I had to choose how to reach them securely from outside my network. The answer wasn't obvious. Both VPN and reverse proxy solutions work, but they protect differently, cost differently, and scale differently. This guide walks through the real tradeoffs so you can pick the right method for your setup.
The Core Difference
A VPN encrypts all your traffic and makes your client appear as if it's inside your home network. Everything routes through the VPN server—every DNS query, every packet, every application.
A reverse proxy sits between the internet and your services, accepting incoming HTTPS requests and forwarding them to your internal apps. Only the traffic destined for those specific services goes through the proxy.
In practice, a VPN is a network-level solution. A reverse proxy is an application-level solution. The difference matters more than you'd think.
Security: Which Is Actually Safer?
I started with the assumption that VPN was "more secure" because it encrypts everything. That's partially true, but incomplete.
VPN advantages:
- All traffic is encrypted end-to-end between your client and homelab
- Your ISP sees no details about what you're accessing
- You're not exposing individual services to the internet at all
- Better for accessing internal resources (printers, NAS shares, SSH) alongside web apps
VPN disadvantages:
- The VPN server itself is a target. If it's compromised, attackers reach your entire network
- You must manage the VPN server's security independently (updates, firewall, fail2ban)
- Slower than direct HTTPS because all traffic tunnels through one server
- More complex to set up and debug
Reverse proxy advantages:
- Each service is isolated. Compromising one doesn't expose others
- Industry-standard, audited software (Caddy, Nginx, Traefik)
- Automatic HTTPS via Let's Encrypt, with strong TLS defaults
- Services only reachable via specific hostnames—no port scanning finds them
- Works great if you only need web app access
Reverse proxy disadvantages:
- Each service is internet-facing (behind the proxy, but still exposed to the web)
- If the proxy is misconfigured, services can leak (bad headers, missing auth)
- Can't easily access non-web resources (SSH, SMB, direct database connections)
- Requires valid domain and DNS setup
My Reverse Proxy Setup: Caddy + Cloudflare Tunnel
For my web services, I prefer Caddy because it's simple and handles HTTPS automatically. Here's what I run:
version: '3.8'
services:
caddy:
image: caddy:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
nextcloud:
image: nextcloud:latest
environment:
- MYSQL_HOST=db
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure_password
- MYSQL_DB=nextcloud
volumes:
- ./nextcloud:/var/www/html
restart: unless-stopped
db:
image: mariadb:latest
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure_password
volumes:
- ./db:/var/lib/mysql
restart: unless-stopped
volumes:
caddy_data:
caddy_config:
And the Caddyfile:
nextcloud.example.com {
reverse_proxy nextcloud:80 {
header_upstream X-Forwarded-For {http.request.remote}
header_upstream X-Forwarded-Proto {http.request.proto}
}
}
jellyfin.example.com {
reverse_proxy jellyfin:8096
}
vaultwarden.example.com {
reverse_proxy vaultwarden:80
}
This setup automatically fetches and renews SSL certificates. I don't expose my services to the raw internet—they hide behind Caddy. If I want to keep my homelab IP private, I use Cloudflare Tunnel (formerly Argo Tunnel) which punches through my firewall without opening ports.
Cost: $0 upfront. Just DNS setup time.
My VPN Setup: Tailscale
For actual remote access to internal resources—my SSH server, NAS, Kubernetes API—I run Tailscale. It's a managed WireGuard network that's trivially easy to set up:
curl -fsSL https://tailscale.com/install.sh | sh
# On the homelab machine
sudo tailscale up
# Visit the auth link, sign in, approve the device
# Now your homelab has a stable Tailscale IP (e.g., 100.0.0.5)
# From your laptop (also running Tailscale)
ssh [email protected]
# Or mount the NAS
mount -t nfs 100.0.0.42:/mnt/storage /mnt/remote
Tailscale is convenient because:
- No server to maintain (Tailscale runs it for you)
- Works through NAT and firewalls automatically
- Free tier supports 3 devices, paid tier scales to teams
- End-to-end encrypted between clients
- Strong audit trails and device approval workflows
Cost: Free for up to 3 devices. Paid plans start at $60/year for more.
VPN: Self-Hosted WireGuard
If you want VPN without proprietary software, WireGuard is the gold standard. It's lightweight, audited, and fast. Here's the basic setup:
On a cheap VPS (I recommend RackNerd—their KVM VPS is excellent value), install WireGuard:
sudo apt update && sudo apt install wireguard wireguard-tools
# Generate keys
wg genkey | tee privatekey | wg pubkey > publickey
wg genkey | tee client_privatekey | wg pubkey > client_publickey
# Server config: /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey =
[Peer]
PublicKey =
AllowedIPs = 10.0.0.2/32
# On your homelab:
[Interface]
Address = 10.0.0.2/24
PrivateKey =
[Peer]
PublicKey =
Endpoint = your-vps-ip:51820
AllowedIPs = 10.0.0.0/24
# Enable and start
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
This gives you a true VPN: encrypted tunnel, full network access, zero logs (you control the server). The trade-off is you manage it yourself—patches, firewall rules, and failure recovery are your responsibility.
Performance: Real-World Latency
From my testing:
- Direct HTTPS (reverse proxy, no VPN): ~25ms ping to homelab
- Tailscale VPN: ~30ms ping, Tailscale's relays add 5–10ms typically
- Self-hosted WireGuard on 3Mbps VPS uplink: ~50ms, but saturates the VPS quickly with multiple simultaneous transfers
For casual browsing (Nextcloud, Jellyfin), differences are imperceptible. For heavy uploads or large file transfers, a reverse proxy is faster because it doesn't funnel all traffic through a single VPN gateway.
Cost Comparison
| Method | Setup Cost | Monthly Cost | Management |
|---|---|---|---|
| Reverse Proxy Only | 1–2 hours | $0 | Updates to Caddy/Nginx |
| Tailscale VPN | 10 min | $0–$60/year | None (managed) |
| Self-Hosted WireGuard | 2–4 hours | $3–10 (VPS) | Full responsibility |
Which Should You Choose?
Use a reverse proxy if:
- You're only accessing web apps remotely (Nextcloud, Jellyfin, Immich, etc.)
- You have a domain and can set up DNS
- You want simplicity and industry-standard tooling
- You prefer zero monthly costs
Use a VPN (Tailscale) if:
- You need access to internal resources (NAS, SSH, databases)
- You want a managed solution with no server maintenance
- You want stronger privacy (Tailscale hides traffic from ISP)
- You're willing to pay ~$5–10/month for convenience
Use self-hosted WireGuard if:
- You need VPN and want to avoid proprietary clients
- You're comfortable managing a VPS and security updates
- You have budget for a cheap KVM VPS (RackNerd's offerings are excellent)
- You want full transparency in your infrastructure
The Hybrid Approach (My Recommendation)
I run both. Caddy reverse proxy handles web services (Nextcloud, Jellyfin). Tailscale handles everything else (SSH, NFS mounts, Kubernetes API). This gives me:
- Clean, simple access to web apps with no VPN overhead
- Secure internal network access when I need it
- Minimal attack surface (no VPN server to compromise)
- Total cost: $0 (Tailscale free tier covers my 3 devices)
If I