5$/month Self Hosted VPN with WireGuard

Published on

This will take you less than 5 minutes to get a private VPN on your own Ubuntu server.

What you need to get started:

  • a VPS (Ubuntu 20.04 LTS preferrably)
  • docker and docker-compose installed

Setting up docker-compose

On the VPS, I suggest to do the following:

Create a folder wireguard/config in your $HOME:

mkdir -p wireguard/config

Inside the wireguard folder (next to the config folder), create the docker-compose file:

vim docker-compose.yml

With the following contents:

version: "2.1"
  image: linuxserver/wireguard
    container_name: wireguard
      - NET_ADMIN
      - SYS_MODULE
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Rome
      - SERVERPORT=51820
      - PEERS=5
      - /home/YOUR_USERNAME/wireguard/config:/config
      - /lib/modules:/lib/modules
      - 51820:51820/udp
      - net.ipv4.conf.all.src_valid_mark=1
    restart: always

Simply change the SERVERURL variable, or delete that line if you want to use the server IP.

Additionally, change the location of your wireguard config path in the volumes section. (use pwd to get the current path you are in).

For more info and environment variables, check out the official linuxserver/wireguard doc.

I’ve used restart: always so that WireGuard comes up after a system restart.

Changed PEERS to 5, so that I have 5 configurations available for my devices.

Launching the container

Start the container in the background with

docker-compose up -d

This will create the needed configurations in the wireguard/config folder.

The structure of your wireguard folder looks something like this

├── config
│   ├── coredns
│   │   └── Corefile
│   ├── peer1
│   │   ├── peer1.conf
│   │   ├── peer1.png
│   │   ├── privatekey-peer1
│   │   └── publickey-peer1
│   ├── server
│   │   ├── privatekey-server
│   │   └── publickey-server
│   ├── templates
│   │   ├── peer.conf
│   │   └── server.conf
│   └── wg0.conf
└── docker-compose.yml

Firewall configuration

If you’re using ufw, simply enable the port 51820 so that you can connect to your server from outside:

ufw enable 51820
ufw reload

If you run sudo ufw status you should see:

Status: active

To                         Action      From
--                         ------      ----
51820                      ALLOW       Anywhere
51820 (v6)                 ALLOW       Anywhere (v6)

Connecting devices

Now you can cat or scp the configurations individually to your devices.

The configurations are located in the config/peerX folder, where X represents the peer number.

E.g. I could cat/scp the configuration in wireguard/config/peer1/peer1.conf and put it in /etc/wireguard/wg0.conf on my host machine.

View the configuration for peer 1 on your server with

cat /home/YOUR_USERNAME/wireguard/config/peer1/peer1.conf

and place it in /etc/wireguard/wg0.conf on your host machine.

If you want to use scp, you could run the following on your local machine:

scp USER@SERVER:/home/YOUR_USERNAME/wireguard/config/peer1/peer1.conf /etc/wireguard/wg0.conf

To connect to your newly created WireGuard VPN from one of your devices, you’ll need to install wireguard-tools.

E.g. apt install wireguard-tools , pacman -S wireguad-tools based on your distro

Here you can find a more detailed explanation

Now you can simply run wg-quick up wg0 and you’re connected to your VPN.

Test it out by running curl ipinfo.io and inspect the output.

Connecting mobile device with QR code

On your mobile device, install the WireGuard client.

Then add a new WireGuard tunnel by creating a new configuration scanning a QR code.

On your VPS run the following to output a QR code on the terminal that you can scan on your mobile device:

docker exec -it wireguard app/show-peer 1

Inspecting connections

If you want to understand who is connected and which profiles are in use, simply run the following on your VPS:

docker exec -it wireguard wg

This will give you more information about your connections with the following output:

interface: wg0
  public key: (redacted)
  private key: (hidden)
  listening port: 51820

peer: (redacted)
  endpoint: (redacted):51820
  allowed ips: (redacted)/32
  latest handshake: 27 seconds ago
  transfer: 5.04 MiB received, 172.64 MiB sent


peer: (redacted)
  allowed ips: (redacted)/32


This was most definitely the easiest way I found to connect computers and mobile devices to your own WireGuard VPN.

Let me know if you had troubles setting it up yourself!

Here, have a slice of pizza 🍕