$docker.recipes
·10 min read·Updated February 2026

Setting Up a Self-Hosted VPN with WireGuard and Docker Compose

Deploy your own WireGuard VPN server in 5 minutes with Docker Compose. Access your home network remotely and secure your traffic on public WiFi.

wireguardvpnsecuritynetworkingdocker-compose

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:latest
4 container_name: wireguard
5 restart: unless-stopped
6 cap_add:
7 - NET_ADMIN
8 - SYS_MODULE
9 environment:
10 - PUID=1000
11 - PGID=1000
12 - TZ=America/New_York
13 - SERVERURL=vpn.yourdomain.com
14 - SERVERPORT=51820
15 - PEERS=phone,laptop,tablet # Client configs to generate
16 - PEERDNS=auto
17 - INTERNAL_SUBNET=10.13.13.0
18 ports:
19 - "51820:51820/udp"
20 volumes:
21 - wireguard_config:/config
22 - /lib/modules:/lib/modules
23 sysctls:
24 - net.ipv4.conf.all.src_valid_mark=1
25
26volumes:
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.

About the Author

Frank Pegasus

DevOps engineer and self-hosting enthusiast with over a decade of experience running containerized workloads in production. Creator of docker.recipes.