In this post I will describe a very practical use case of running a Wireguard VPN server on Docker. This time I will be creating a docker container using docker-compose method.

Why use a VPN?

VPN services offer several benefits to users. Firstly, they provide enhanced online security by encrypting internet traffic, making it difficult for hackers or third parties to intercept sensitive information. Secondly, VPNs allow users to browse the internet anonymously, protecting their privacy and preventing websites from tracking their online activities. Additionally, VPNs enable users to bypass geo-restrictions and access content that may be blocked in their region. Lastly, VPNs can improve internet speed and performance by reducing network congestion. Overall, VPN services offer a secure, private, and unrestricted internet experience.

Self-hosted VPN server or VPN service provider

Using a reliable VPN service provider is a good and easy option. There are a quite a few options out there, but my personal preference is ProtonVPN. I switched to using their paid e-mail account a while back and my current plan also includes VPN. Another option that some privacy professionals also recommend PIA. In my current setup, I have segmented my home network using VLANS and I route my Internet traffic via several VPN endpoints (or locations). VPN client connections are set up in my pFsense firewall, which I run within Proxmox as a VM.

This above mentioned setup works perfectly well and I have an ability to chose the route for my devices and networks, and ProtonVPN seems to be working very fast. Most of the time I get 95% of my bandwidth speed with OpenVPN protocol. My server runs on N5105 processor which supports AES-NI, that is essential for OpenVPN to operate on faster speeds.

However, there are situations when self-hosting a VPN server is required. The main reason for me is, that some services, such as banks, blacklist VPN service provider’s IPs. I have noticed that at least one of my banking apps is not working when I am behind a ProtonVPN connection. At home I could simply switch to a different network that bypasses VPN to use this application, but when I travel, I would like to have a connection to my bank without having to use an unsecure network of hotel, airport, etc.

Self-hosting is also an option when you need to connect to your home network. You can simply run a VPN server in your homelab environment, for example.

Setting up a Wireguard server on Docker

This instruction assumes that you already have docker installed and set up. I have covered the process of installation in my previous post, so please check it out if you need to.

I followed a great tutorial by Christian Lempa who also has a YouTube video on the setup, however I needed to make some slight changes. The original documentation is available at https://hub.docker.com/r/linuxserver/wireguard.

The reason that I am setting up a Wireguard server instead of OpenVPN is that I will be connecting to it from my travel router and Wireguard is generally faster than OpenVPN and does not require that much of resources. My travel router is a GL-SFT1200 (Opal) by GL.iNet, that I purchased from amazon recently.

Create a docker-compose file

It is a good idea to place it in a separate directory. You can either create it within /opt or your home directory.

mkdir /opt/wireguard-server

Next using an editor of your choice, edit the docker-compose file. I am using micro, so in my case the command is micro /opt/wireguard-server/docker-compose.yaml

Here is how my file looks like:

---
version: "2.1"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE 
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/London
      - SERVERURL=auto 
      - SERVERPORT=51820 
      - PEERS=1 
      - PEERDNS=1.1.1.1
      - INTERNAL_SUBNET=10.13.13.0 #optional
      - ALLOWEDIPS=0.0.0.0/0 #optional
      - PERSISTENTKEEPALIVE_PEERS= #optional
      - LOG_CONFS=true #optional
    volumes:
      - /opt/wireguard-server/config:/config
      - /lib/modules:/lib/modules #optional
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: always

NB! Your PUID and PGID might be different. You can check it using id <username> command. You can also change other settings, such as ports, peerdns of your choice and the amount of peers required.

Start the server

docker-compose up -d

Share the config files with clients

When the docker container is up and running the config file will be automatically created in you ./config folder. You can copy the config file to your client via scp for example. There is also a cool feature to show a QR code if you want to connect to WireGuard from your mobile device by issuing the following command:

docker exec -it wireguard /app/show-peer <peer-number>

And this is basically it. I ran the container on my Ubuntu 22.04 docker host VM and docker even took care of all the port configuration and connecting to the server worked out of the box.