01Why Self-Host a VPN?
Commercial VPN services promise privacy, but you're trusting them with all your internet traffic. A self-hosted VPN gives you actual privacy: your traffic is encrypted between your device and your own server, and no third party can see or log it.
Beyond privacy, a self-hosted VPN lets you access your home network from anywhere. Connect to your self-hosted services, access files on your NAS, or manage your home lab from a coffee shop — all through an encrypted tunnel.
WireGuard is the best VPN protocol for self-hosting: it's fast (the kernel module handles encryption at near-wire speed), simple (the configuration is a handful of lines), and modern (uses state-of-the-art cryptography with a tiny attack surface).
02WireGuard Docker Compose Setup
The LinuxServer.io WireGuard image makes setup trivial:
[docker-compose.yml]
1services: 2 wireguard: 3 image: lscr.io/linuxserver/wireguard:latest4 container_name: wireguard5 restart: unless-stopped6 cap_add: 7 - NET_ADMIN8 - SYS_MODULE9 environment: 10 - PUID=100011 - PGID=100012 - TZ=America/New_York13 - SERVERURL=vpn.yourdomain.com14 - SERVERPORT=5182015 - PEERS=phone,laptop,tablet # Client configs to generate16 - PEERDNS=auto17 - INTERNAL_SUBNET=10.13.13.018 ports: 19 - "51820:51820/udp"20 volumes: 21 - wireguard_config:/config22 - /lib/modules:/lib/modules23 sysctls: 24 - net.ipv4.conf.all.src_valid_mark=12526volumes: 27 wireguard_config: Set PEERS to a comma-separated list of client names. WireGuard will auto-generate a config file and QR code for each peer in the /config directory. Scan the QR code with the WireGuard mobile app and you're connected.
03Connecting Clients
After starting the container, find the client configurations in the config volume:
Each peer gets a folder containing a .conf file and a PNG QR code. For mobile devices, install the WireGuard app and scan the QR code — that's the entire setup. For desktop clients, import the .conf file into the WireGuard application.
The generated configuration routes all traffic through the VPN by default (AllowedIPs = 0.0.0.0/0). If you only want to access your home network (split tunnel), change AllowedIPs to your home subnet (e.g., 10.13.13.0/24, 192.168.1.0/24).
I use split tunneling on my phone to only route home network traffic through the VPN, and full tunneling on my laptop when I'm on public WiFi.
04Accessing Your Services Remotely
With the VPN connected, you can access any service on your home network by its internal IP or Docker hostname. No need to expose services publicly or set up Cloudflare Tunnels — the VPN gives you secure, direct access.
This is my preferred approach for admin panels and sensitive services. Public-facing services (personal websites, public APIs) go through Cloudflare Tunnel. Everything else — Traefik dashboard, Portainer, database admin panels, monitoring — is only accessible via VPN.
The WireGuard protocol is lightweight enough that it works well even on mobile connections. Battery impact is minimal compared to OpenVPN, and the connection is stable enough to survive network transitions (WiFi to cellular and back).
Check out our security recipes for WireGuard configurations and other VPN solutions like Tailscale and OpenVPN.