In this guide, we are going to see how to implement a Wireguard Docker Compose configuration to deploy our Wireguard VPN docker. Docker compose makes it very simple to deploy Wireguard VPN.
But before we dive in, let's cover some basics.
Table of Contents
- Background Information for Wireguard Docker Compose Setup
- Membership Required
- FAQ
- Concluding Remarks on Wireguard VPN Docker
Background Information for Wireguard Docker Compose Setup
WireGuard Basics
A lot of words have already been spent on Wireguard, but here's a quick review on it anyway (source Wikipedia):
WireGuard is a communication protocol and free and open-source software that implements encrypted virtual private networks (VPNs), and was designed with the goals of ease of use, high speed performance, and low attack surface. It aims for better performance and more power than IPsec and OpenVPN, two common tunneling protocols. The WireGuard protocol passes traffic over UDP.
Wireguard vs IPsec vs OpenVPN
Up to now, it is faster and more performant than its primary competitors IPsec and OpenVPN:
These benchmarks are old, crusty, and not super well conducted. In the intervening time, WireGuard and IPsec have both gotten faster, with WireGuard stil edging out IPsec in some cases due to its multi-threading, while OpenVPN remains extremely slow.
But they are useful to give an idea of the superiority of the protocol.
If we ever wanted to test it by ourself, we can find some scripts here.
It is also well documented, easy to implement, cross-plattform and, last but not least, open-source and easy to audit, as the source code is way lighter than his competitors.
For a quick introduction to this amazing protocol, review our previous WireGuard articles:
Other Posts in the Wireguard Series:
- Wireguard VPN Intro in 15 min: Amazing new VPN Protocol
- Complete Wireguard Setup in 20 min – Better Linux VPN Server
- Wireguard Windows Setup: Powerful VPN for Windows
- Wireguard Mac OS Client Setup – The sleek new VPN
- Wireguard Android Client Setup – Simple and Secure VPN
- Ultimate WireGuard Docker Compose: with CF and Traefik Support
Docker Basics
We should be already familiar with Docker, anyway:
Docker is a tool that is used to automate the deployment of applications in lightweight containers so that applications can work efficiently in different environments in isolation.
If you need help installing and configuring docker, I suggest to read these Anand's articles and set it all EASILY:
I also recommend to take some time and read these other two articles, that will also come in handy for other purposes:
After this short smattering, let's get our hands dirty starting with docker compose configuration file.
1. Wireguard Docker Compose Configuration
The configuration reported ahead is the simplest, shortest, minimalist configuration that we need to use to have a Wireguard VPN Server up and running. We will use the WireGuard Docker image from Linuxserver.io:
version: '3.9' services: wireguard: image: lscr.io/linuxserver/wireguard:latest container_name: Wireguard cap_add: - NET_ADMIN environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - PEERS=Profile1,Profile2,OtherProfile volumes: - $DOCKERDIR/appdata/wireguard:/config ports: - 51820:51820/udp sysctls: - net.ipv4.conf.all.src_valid_mark=1 restart: unless-stopped
Naturally, we need to setup a port forward from external port 51820 to our Docker Compose Server, on the same port: I only used default Wireguard Server port in all the configuration to keep it simple, but no one forbids us to set different port numbers.
Port 51820 from the WireGuard Docker container is mapped to the same port on the host machine.
Explanation of Docker Compose for Wireguard
Here is a schematic of what's going on:
Changing Default Wireguard Port
As I mentioned before, we could set different ports keeping in mind a few things. Here are a few things to ensure when using a port other than the default 51820:
- Remember to do a port forward from that port to the docker compose stack's port (quite obvious).
- Set it in the "ports" section of wireguard service in the yaml file:
ports: - 51700:51820/udp # First number is the port used by docker compose stack, second one is the port used by Wireguard server docker
- Set it in the "environment" section of wireguard service in the yaml file:
environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - PEERS=Profile1,Profile2,OtherProfile - SERVERPORT=51699
In this case, we need to adjust the "ports" section too:
ports: - 51700:51699/udp
Wireguard Peer Configuration
After this, basically, we could retrieve our configuration file or QR code and get instantly connected to our network from the outside.
- Configuration files: These files are located inside the /config/peer_ProfileName folder (folder names are the same chosen in the PEERS environment variable plus the "peer_" suffix (ex: peer_Profile1)) and are named like "peer_Profile1.conf":
- QR codes:
environment: [...] - PEERS=Profile1,Profile2,OtherProfile [...] volumes: - $DOCKERDIR/appdata/wireguard:/config
We could save and import them (Android/iOS app, Windows/Linux/Mac client) to get the configuration of the corresponding profile.
To display the QR code(s), we need to run a command inside the Wireguard server docker, followed by the names of the profiles we need:
# Run this on the docker compose stack terminal # this will be executed inside the Wireguard server docker, # thanks to docker exec command docker exec -it Wireguard /app/show-peer Profile1,Profile2
And like magic, the codes are displayed directly on our terminal, ready to be scanned from our Android/iOS app. Of course, in the profile folders, mentioned before, there are the .png files with the QR codes, but I strongly discourage their use because there's nothing more beautiful than seeing them displayed directly on the terminal. TRUST ME!
2. Wireguard Docker Compose Configuration with Optional Fields
The above standard Wireguard VPN docker compose works great. But why stop there if you can customize a few more options to enhance the experience?
I'll write the optional fields commented, then we're going to discuss them:
version: '3.9' services: wireguard: image: lscr.io/linuxserver/wireguard:latest container_name: Wireguard # networks: # t2_proxy: # ipv4_address: 192.168.2.10 cap_add: - NET_ADMIN environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ # - SERVERURL=<OUR PUBLIC IP> # - SERVERPORT=51820 # - PEERS=Profile1,Profile2,OtherProfile # - PEERDNS=<DNS IP> # - INTERNAL_SUBNET=192.168.10.0/24 # - ALLOWEDIPS=0.0.0.0/0 # - LOG_CONFS=false volumes: - $DOCKERDIR/appdata/wireguard:/config ports: - 51820:51820/udp sysctls: - net.ipv4.conf.all.src_valid_mark=1 restart: unless-stopped
Networks Block
This is used if we want to set a local static ip to our Wireguard server docker (check Anand's guide for more info about this configuration).
Environment Variables
- - SERVERURL: our public IP, if not specified it will be automatically detected. We could also use our customized domain name.
- - SERVERPORT: needed if we want to use a different port for our Wireguard Server Docker.
- - PEERS: optional field but useful, as we can choose the profile names we want and avoid wasting time trying to figure out the association between users and random name configuration files.
- - PEERDNS: the DNS server, if we have an internal DNS solution like Pi-Hole or AdGuard Home we can use it.
- - INTERNAL_SUBNET: the subnet used for peers IP.
- - ALLOWEDIPS: we can configure the allowed IP that could be reached through the tunnel. If configured with 0.0.0.0/0, or omitted, all the traffic from the client will be routed through the tunnel, and all the devices on the network would be reachable.
- - LOG_CONFS: the generated QR codes are visible in the docker log.
3. Cloudflare & Traefik Configuration (OPTIONAL)
The docker compose configuration we've just analyzed, with the appropriate port forwarding, is enough to have our Wireguard Server Docker up and running. But if we use services, like Cloudflare, to hide our public IP we need to have some trade-offs.
Cloudflare Proxy Proxied Ports
In the Cloudflare Free Plan the port proxied by default are:
HTTP ports supported by Cloudflare:
- 80
- 8080
- 8080
- 8880
- 2052
- 2082
- 2086
- 2095
HTTPS ports supported by Cloudflare:
- 443
- 2053
- 2083
- 2087
- 2096
- 8443
Ports supported by Cloudflare, but with caching disabled:
- 2052
- 2053
- 2082
- 2083
- 2086
- 2087
- 2095
- 2096
- 8880
- 8443
All of these ports could be only used to proxy HTTP and HTTPS, not suitable for our purposes.
Using Domain Names with Wireguard
So, if we still want to use our customized domain name for Wireguard, we have two options:
- Expose our real ip, disabling the proxy function from the Cloudflare dashboard.
- Configure a Spectrum application (CLOUDFLARE PAID PLANS ONLY) from Cloudflare dashboard, but I cannot guarantee that this will work as I haven't tested this option. If someone want to try this option, this is the Cloudflare page with instructions to do so.
If we don't care about having our customized domain name, we can of course use our public ip in the Wireguard server docker configuration (environment variable SERVERURL).
Wireguard Server Docker with Traefik Reverse Proxy
Let's assume we have chosen to expose our real ip and use our custom domain name, now we could configure our reverse proxy, Traefik in this case, in order to forward the requests to the Wireguard Server Docker.
This step could safely be skipped, because, as I said before, our configuration is already working without the need for further modifications, but is very useful for keeping monitored which ports we've exposed, directly from our Traefik dashboard, on our Docker Compose Stack.
Let's edit our docker compose configuration file docker-compose.yml:
version: '3.9' services: traefik: #### other traefik compose options not shown #### ports: # Port WIREGUARD - target: 51820 published: 51820 protocol: udp mode: host command: - --entryPoints.wg.address=:51820/udp wireguard: image: lscr.io/linuxserver/wireguard:latest container_name: Wireguard cap_add: - NET_ADMIN environment: - PUID=$PUID - PGID=$PGID - TZ=$TZ - SERVERURL=wireguard.mydomain.com - PEERS=Profile1,Profile2,OtherProfile volumes: - $DOCKERDIR/appdata/wireguard:/config # Ports section could be omitted as Traefik # will take care of it # ports: # - 51820:51820/udp sysctls: - net.ipv4.conf.all.src_valid_mark=1 restart: unless-stopped labels: - "traefik.enable=true" - "traefik.udp.routers.wg.entrypoints=wireguard" - "traefik.udp.routers.wg.service=wireguard-udp-svc" - "traefik.udp.services.wg-udp-svc.loadbalancer.server.port=51820"
Personally, I prefer to not expose real IP using "DNS only" option from Cloudflare. This is because if we have more than one domain name proxied and our real public IP would be discovered and associated to one of them, all the extra protection layer provided by Cloudflare becomes futile.
Now that everything has been configured, the only remaining thing to do is start Wireguard Server Docker and spread some love for this amazing protocol.
!BONUS TRACK! Ad-Blocking on-the-go
Time for extra content that could make our life easier.
FAQ
What is the difference between Wireguard, Wireguard Server Docker, Wireguard VPN docker?
"Wireguard VPN Docker" and "Wireguard Server Docker" are basically the same thing, that is our Wireguard Server deployed inside a docker container. "Wireguard" the protocol.
Can WireGuard run in Docker?
Yes, Wireguard Server can run in Docker or can be configured directly on Linux. Server installation could also be deployed on Windows, but this configuration is not officially supported.
How secure is WireGuard?
Wireguard uses cryptographic protocols and primitives that are consolidated and reviewed by cryptographers, so the data sent through the VPN tunnel can be considered safe. Like all the protocols, we have some known limitations listed on the official Wireguard site.
Does WireGuard work on Linux?
Wireguard client runs on every operating system (Android, iOS, Windows, Linux, Mac), the server runs officially on Linux only.
How do I host a WireGuard VPN?
We could choose different ways: we could use docker to host our Wireguard Server Docker, or we could use Linux to install and configure our Wireguard Server.
Concluding Remarks on Wireguard VPN Docker
We have written a lot about Wireguard and a lot about Docker. Wireguard has simplified what has long been a cumbersome task with lots of overhead. The result is increased performance with some or better security.
Therefore, it is no surprise that some of the major VPN providers (shout out to our favorite VPN provider, Surfshark) are starting to offer this protocol.
With this guide, we combined two of our favorites to install WireGuard VPN server using Docker. We also tried to address some advanced scenarios such as working with Cloudflare and Traefik. We hope that this simple WireGuard Docker Compose guide get you started with enough basics to level up your setup and knowledge.