Self-hosted VPN server (Wireguard)

Motivation

While I was abroad I needed to have the European IP address to access some of the streaming services so instead of paying the VPN services from other, I’ve decided to self-host my own and learn about VPN-s.

Since I already have my Docker Swarm cluster set up on my cloud VM-s, I’ve decided to deploy the VPN server on Docker Swarm as opposed to just spinning it up on one of the VM-s through Docker.

I’ve chosen the Wireguard as my solution: it’s free, open-source, very easy to setup and requires minimal configuration.

Implementation

Below is the docker compose file for Docker Swarm deployment:

version: "3.8"
services:
  wireguard:
    image: linuxserver/wireguard
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=0
      - PGID=0
      - TZ=Europe/London
      - SERVERPORT=51820 #optional
      - PEERS=1 #optional
    volumes:
      - /mnt/storage/opt/wireguard-server/config:/config
      - /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped

The prerequisite is to create the folder /mnt/storage/opt/wireguard-server/config beforehand because Docker requires, in the case of host path volumes, for folders to exist beforehand. Since this configuration folder is located in the NFS storage, which is the mounted filesystem shared by all Docker Swarm nodes, it’s necessary to log in to one of the VMs and create the folder in this filesystem.

Note: If we want more peers, edit the environment variable PEERS and redeploy the stack. This will create an additional configuration folder for newly created peers.

To deploy the stack, run this command:
docker stack deploy -c docker-compose-swarm.yml wireguard-stack

Once the stack is deployed, we want to set up the client for this VPN server. I am using a mobile phone device, so we will be sharing the configuration through a QR code.

To display the QR code inside the terminal, install the tool catimg:
sudo apt-get install catimg

catimg /mnt/storage/opt/wireguard-server/config/peer1/peer1.png

Open up WireGuard on your phone, in my case an iPhone, and scan the QR code to set up the host.

Note: If you are using the desktop client, the folder will also contain the peer1.config file. Copy this file to your desktop machine and import it into the WireGuard app to set up the VPN host seamlessly.

After everything’s done, head to whatsmyip.com, and voila, now we are browsing the web through Hetzner’s Cloud VM located somewhere in Germany!