WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry.
This article will showcase the procedure how to install Wireguard VPN server with Docker. Wireguard is another good VPN option besides OpenVPN. Wireguard doesn’t have an official Docker image yet, so we’ll be using the Wireguard Docker image from linuxserver.io – This exact image used in this post: Docker Hub (and Github page)
- Docker installed and running.
For docker installation, you can refer to this post or check out the official documentation.
If you run distros such as – Ubuntu, Debian, Raspbian, then you can use the official Docker quick install script:
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
Then add user to the docker group, if you want. That is if you want to run docker commands without sudo.
sudo usermod -aG docker <username>
If you have a firewall running(which is highly recommended), it’s necessary to have open ports for Wireguard, otherwise, you’re not going to be able to establish the connection with the Wireguard server.
sudo ufw allow 51820
sudo iptables -I INPUT -p tcp -m tcp --dport 51820 -j ACCEPT or sudo iptables -A INPUT -p tcp -m tcp --dport 51820 -j ACCEPT
Setting up WireGuard
Now that Docker has been installed, we can move on to setting up the VPN itself. For this, it is best to have a domain pointing to your machine that you can use for VPN purposes. If you do not have one, use
auto instead of a domain in the command below.
You will also need to know how many devices that you will have that will use the VPN at the same time. In my case, I have a laptop, tablet and phone that could be using the VPN at the same time. From these devices, you will need to make a comma separated list of device names (e.g.
laptop,tablet,phone) these can be named anything you’d like.
Now run the command below. Make sure to put your domain in for
SERVERURL= and your list of devices for
docker run -d \ --name wireguard \ --cap-add=NET_ADMIN \ --cap-add=SYS_MODULE \ -e PUID=1000 -e PGID=1000 \ -e TZ=Europe/London \ -e SERVERURL=wireguard.yourdomain.com \ -e PEERS=laptop,tablet,phone \ -e PEERDNS=auto \ -p 51820:51820/udp \ -v wireguard_config:/config \ -v /lib/modules:/lib/modules \ --sysctl="net.ipv4.conf.all.src_valid_mark=1" \ --restart=unless-stopped \ linuxserver/wireguard
Here’s what all of that means:
--name wireguard– This names the container which makes it easier for using in commands later (rather than using the container’s ID).
--cap-add=NET_ADMIN --cap-add=SYS_MODULE– This gives the container extra permissions on the host system. Specifically, it is allowed to modify network interfaces and install kernel modules respectively (more on that below).
-e ...– Each of the
-earguments sets an environment variable inside the container, these are used to configure the application that is running inside the container.
-p 51820:51820/udp– This listens for traffic on UDP port 51820 (left of the colon) on the host and passes it through to the container on port 51820 (right of the colon). If something else was using that port, you could change the one on the left of the colon to something else (for WireGuard, you’d also have to set
-e SERVERPORT=to reflect the new port too)
-v wireguard_config:/config– This mounts the
/configfolder in the container to a Docker volume called
wireguard_config(this could also be changed to a folder on the host, for example
/home/jakew/wireguard). This particular volume would be stored at
-v /lib/modules:/lib/modules– This is the same as before, but we are just mounting the folder
/lib/modulesto the same place on the host (more on that below).
--sysctl="net.ipv4.conf.all.src_valid_mark=1"– This sets a kernel parameter.
--restart=unless-stopped– This makes sure that the container starts again on crashes and host restarts (unless it is manually stopped in which case it will not be started again when the host reboots).
linuxserver/wireguard– This is the image that is being used. This is the name of the image which will be downloaded from Docker Hub which is a repository of Docker images.
Pressing enter will pull (download) the image and start the container in the background. You will get a long string of characters which is the container’s ID. The VPN will initially take a little while to start up.
Why the SYS_MODULE and /lib/modules?
The reason that the VPN takes a little while to start up for the first time and the reason that we give the container permission to install kernel modules and mount the
/lib/modules folder is because WireGuard is actually run inside the Linux kernel. This is why it has such great performance and security.
Getting client configurations
WireGuard will generate a configuration for each peer that we defined earlier on. These configurations contain connection information like the IP/domain of the VPN server and certificates for authentication.
The easiest way to get the client configuration onto your device is to scan the generated QR codes when the container starts. These are only shown on the first run, so if you missed them you’ll need to get the files instead. We can look at them by using the following command and simply scanning the QR code with your phone or tablet.
docker logs wireguard
It’s best to also save the configurations to your local machine so that you have them for future use. To use these, simply open the
.conf file onto your device and open it in the WireGuard app. This command will copy the configurations to your home directory.
sudo cp /var/lib/docker/volumes/wireguard_config/_data/peer*/*.conf ~
Now set up a device with a configuration and make sure that it works correctly. If it connects it will most likely be working properly, but it might be worth checking your IP address to make sure that it matches what you would expect (e.g. the IP address of your cloud server).
Setting up automatic updates
Although the VPN is now working, it may be worth setting up automatic updates to make sure you have the best security. There is a tool called watchtower that is run inside a Docker container that checks all of your other Docker containers for updates and will automatically download the update and restart the container seamlessly.
docker run -d \ --name watchtower \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower wireguard
If you have more containers that you would like to keep updated, it would be worth checking out the watchtower documentation to make sure that you have it set up properly for how you would expect. I have mine set up by adding a label to each container that I would like to have updates on and leaving critical containers to be updated manually. You can also configure other useful things like notifications when containers get updated.
Installing the Wireguard client and obtaining the peer configuration
On Linux devices(PCs and laptops), the client setup is a bit different. Client installation and configuration is all done via terminal. First, Wireguard install:
sudo apt install wireguard
Wireguard client is also available for other distributions and for Windows as well. If you need client for other clients, check out the docs.
Next, create the Wireguard interface:
ip link add dev wg0 type wireguard
and double check if it’s present via command: ip -a. If you encounter issues with this, wireguard docs has other methods as well and covered troubleshooting.
It should look something like this:
Leave it as is for now and move on the server. We need to acquire the peer configuration directly from the server first, copy the configuration and paste it on our linux client device.
The default location of the peer configuration is located at:
You can copy it(if necessary) to backup it or access the peer configuration directly:
sudo cp /var/lib/docker/volumes/wireguard_config/_data/peer*/*.conf ~
This will copy all the peer configurations to the home directory and then on the home directory print the file with cat:
sudo cat peer_laptop.conf or sudo nano peer_laptop.conf
or access the peer configuration directly:
sudo cat /var/lib/docker/volumes/wireguard_config/_data/peer_laptop/peer_laptop.conf
If you get the permission denied error with sudo command as well, that means the configuration can be accessed only as root. If that’s the case, then just login as root with – sudo su and again run either of the commands from before without sudo.
Configuring the client interface and establishing the connection
After you have copied the configuration, return to your linux device, create the peer configuration file(just for the example we’re going to create the config at home directory):
sudo nano wireguard-vpn.conf
and paste in the peer config, save and exit.
Lastly run this command to autoconfigure the wireguard interface, to activate it and after that, it should automatically connect to your server:
sudo wg-quick up wireguard-vpn.conf
You can double check it with – ip a and with ping to the vpn server or with a what’s my ip service.
To disconnect, just run the same command again but with down argument:
sudo wg-quick down wireguard-vpn.conf
What we covered in this post are the steps how to install Wireguard VPN server with Docker. This method is rather quick to setup and it’s easily adjustable, if you want to like add or remove clients. But, If you prefer more the solution with OpenVPN, there’s the same procedure with OpenVPN
https://github.com/hautph/wg-easy ( WireGuard + Web UI )