PINAC Pt. 1: Running a WireGuard VPN in Docker
This is the first part in a five-part series which will cover WireGuard, Shadowsocks, Monero, I2P and Tor.

Lynett Simons
Photo by Aron Van de Pol / Unsplash
This is the first part in a five-part series which will cover WireGuard, Shadowsocks, Monero, I2P and Tor.
As some of you may know, (me, Lyn Simons, author of this post) I'm British. And many of the people who live on this island have expressed discontent with the government's Online Safety Act, including me.
So without further ado, let's talk about how you can run your very own WireGuard VPN on your very own VM to bypass geoblocks and government censorship.
Why would you do this?
- You like tinkering and doing things yourself
- You like learning some basic stuff about networks
- You want to get an American IP address
- Commercial VPNs get blocked too much
- You don't trust commercial VPNs' no-log policies
Prerequisite: Docker

We're big fans of Docker here at Altivox. It helps keep our systems online, and it can help you as well.
First of all, install Docker Engine using the installation guide. Depending on your distribution of choice (the first setup panel gives you various options), you might have to use a different set of commands, but here's the Ubuntu commands:
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Add your user to the Docker group
sudo usermod -aG docker $USER
newgrp
# Test if it works
docker run hello-world
After running the hello world command to verify that Docker works, we can move on to the next steps.
The commands earlier already installed Docker Compose for you, so luckily you don't have to install it manually. If you used a different install guide or have a different distro, you'll have to install the package, usually named docker-compose
.
What are VPNs?
(If you know what they are and how they work, just skip ahead.)
A VPN stands for Virtual Private Network. From back to front, it means:
- Network, which allows computers to talk to each other.
- Private, in the sense of restricted, so not everyone can access it
- And virtual, because it creates an overlay network on top of a physical one, like a "virtual machine"
It does not necessarily mean anonymity technology! There are VPNs used to allow people access into high-security corporate networks or homelab networks such as Tailscale, Cloudflare WARP and the like.

Since VPNs are networks, your device once connected gets its own IP address inside the VPN, just like how your router assigns IP addresses to your devices on your local network. You also take on the IP address of the server, just like how your computer takes on the external IP address of your router when you're connected to it.
Creating the stack
SSH into your VM. Our first step is to create a folder for you to put your Docker Compose stacks, keeping things organised. I suggest /opt/stacks/wireguard
, but any place works (as long as you can remember it!)
You'll have to use sudo for this because /opt/stacks
is a privileged location that only root can access.
sudo mkdir -p /opt/stacks/wireguard
cd /opt/stacks/wireguard
The -p
option means "create parent", so it'll create wireguard as well as the stacks directory if you haven't done so already. This also makes you enter the directory.
Next, you'll want to open the file compose.yml
inside that directory. You can use nano as a text editor as it comes preinstalled in nearly all Linux server OSes (sudo nano compose.yml
), but vim and micro are also fine choices.
We'll be using the linuxserver/wireguard Docker image made by the LinuxServer team.
Paste the following in:
version: 2.1
services:
wireguard:
container_name: my-wg-vpn
image: lscr.io/linuxserver/wireguard:latest
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- SERVERURL=vpn.alt.box
- SERVERPORT=51820
- PEERS=alice,bob,charlie
- INTERNAL_SUBNET=10.13.13.0
- ALLOWEDIPS=0.0.0.0/0
- LOG_CONFS=true
volumes:
- ./config:/config
- /lib/modules:/lib/modules
ports:
- 51820:51820/udp
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped
Now, you'll want to modify a few things depending on your setup. You must edit SERVERURL
to point to your server's public IP address or a domain pointing to it. You can't change the server URL or the subnet later without invalidating existing configs!
Additionally, edit PEERS to automatically generate a bunch of client configs (information used by a device to connect to your VPN). So for example, if you have PEERS set to alice,bob,charlie
, it'll create three named configs, allowing three simultaneous connections from these different devices.
ALLOWEDIPS is a list of IP subnets that will be tunneled through the VPN. If it's set to 0.0.0.0/0, it will tunnel all traffic through it by default.
When you're done configuring, you can start it up by running docker compose up -d
to create the stack in detached mode.
Using your VPN
How do you get your configs to your devices, you may ask? Very simple: simply go to the config folder (it should be created automatically) and look for your device configs. If they're named, they should be easily accessible for you to copy to the respective device.
cd /opt/stacks/wireguard/config
ls

Different OSes have different ways for adding VPNs. You'll usually need to install the WireGuard app for your OS from the official website or applicable software store, but sometimes it comes with your system, such as in GNOME.
For desktops, you should be able to copy over the config file from the directory and use that in the WireGuard app. (If you're lazy, just cat
the file and copy it off your terminal.)
This Docker image also prints out configs in the form of QR codes to container logs by default, so you can simply run the command docker logs my-wg-vpn
(if you were paying attention, we set that container name in the compose file) to show them. This is useful for mobile devices as they can simply scan the code with their cameras.
If you didn't catch the QR code in logs, it's also saved as peer_YOUR-DEVICE-NAME.png
in the respective peer folder.
Happy hacking, stay safe, and until next time when we get to setting up a proxy protocol: Shadowsocks!
About the Author

Lynett Simons
Lyn is a programmer forced to be a vibe designer and sales lead. She rants about the evils of serverless on the Altivox Networks Twitter account.