Skip to content
Go back

Wireguard VPN Server in Docker

· Updated:
By SumGuy 5 min read
Wireguard VPN Server in Docker

Install Docker

Install docker on Ubuntu/DebianInstall docker on Ubuntu/Debian

Why Wireguard

WireGuard VPN is a newer VPN protocol that is designed to be faster, more secure, and simpler than older VPN protocols such as OpenVPN. WireGuard uses modern cryptographic techniques to provide better security and performance compared to other VPN protocols. Here are some of the main advantages of using WireGuard VPN over OpenVPN:

In summary, WireGuard VPN offers faster speeds, better security, simpler configuration, and improved battery life compared to OpenVPN. These advantages make WireGuard a great choice for users who want a faster and more secure VPN experience. However, it should be noted that WireGuard is still a relatively new protocol and may not be as widely supported as OpenVPN by VPN providers and clients.

Create docker-compose.yml

Create a new directory for your project and create a file named docker-compose.yml inside it. add the following to it.

---
version: "2"
services:
wireguard:
image: lscr.io/linuxserver/wireguard:latest
container_name: wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC # e.g. America/New_York
- SERVERURL=wireguard.domain.com #External IP or domain name for docker host. can be auto, the container will determine the IP
- SERVERPORT=51820 # server port
- PEERS=desktop,tablet,phone,phone2,fridge,toaster,cat_collar #names of all devices you want to add to this vpn
- PEERDNS=1.1.1.1 #dns server IP to use with wireguard (cloduflare shown)
- INTERNAL_SUBNET=10.13.13.0 #your internal subnet for the VPN
- ALLOWEDIPS=0.0.0.0/0 # what IPs can connect to your server? leave at 0.0.0.0 unless you have a specific reason.
- PERSISTENTKEEPALIVE_PEERS= #optional
- LOG_CONFS=true # Generated QR codes will be displayed in the docker log.
volumes:
- ./config:/config
# - /lib/modules:/lib/modules # only enable if using custom wireguard modules.
ports:
- 51820:51820/udp
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped

the ENV variables are explained in the comments but the rest of the commands are explained below :

Operations

docker compose up -d : download images as needed and turn on the container. docker compose down : bring down the container and disable the network. leaves the volumes on disk.

More updated info can be found at : https://docs.linuxserver.io/images/docker-wireguard

When Peers Can’t Connect: Common Gotchas

You got the container running, generated your peer configs, scanned the QR code on your phone — and then nothing. Welcome to the club. Here are the usual suspects.

Port 51820/UDP isn’t actually open. WireGuard is UDP-only, and a lot of routers (and cloud providers) block or ignore UDP by default. Double-check your router’s port forwarding rule, and if you’re behind a cloud firewall (AWS security groups, GCP firewall rules, etc.), make sure UDP 51820 is explicitly allowed inbound. TCP rules don’t count.

SERVERURL is wrong. If you set it to your LAN IP (192.168.x.x), your phone will try to reach that address from outside your network and obviously fail. Set it to your public IP or a dynamic DNS hostname. If your ISP gives you a changing IP, something like ddns.net or Cloudflare DDNS is your friend.

The kernel module isn’t loaded on the host. The container needs wireguard in the host kernel. On most modern systems it’s built-in, but some minimal VPS images don’t include it. Check with:

Terminal window
lsmod | grep wireguard

If nothing comes back, install it:

Terminal window
sudo apt install wireguard-tools linux-modules-extra-$(uname -r)
sudo modprobe wireguard

Log your way to the answer. The linuxserver image outputs generated peer QR codes and connection info to the container logs. When something’s off, this is the first place to look:

Terminal window
docker compose logs -f wireguard

Look for PEERS generated lines and any wg0.conf parsing errors. Nine times out of ten the problem is visible right there — a missing env var, a bad subnet definition, or a peer name with a space in it (don’t do that).

One more thing: if you’re testing from inside your home network, the VPN handshake will fail or behave weirdly because your router likely doesn’t support NAT loopback. Test from a mobile connection or a VPS, not from the same LAN the server lives on.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
WireGuard Is Fast, But You're Leaving Performance on the Table
Next Post
WordPress on PHP-FPM & Caddy in Docker

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts