Wireguard
- Install Wireguard
- Configure clients
- Access the secure network
Introduction
Using a VPN allows remote access to a serverβs local resources without exposing them to the internet. Itβs a clean and secure way to access services like SSH without exposing the port publicly. With a VPN, you can securely connect to your network from anywhere and make devices on different networks communicate.
Here we will use Wireguard, a secure and high-performance VPN server, using containers:
- wg-easy as the server, providing a very simple web UI to manage connections and download config files (including QR codes for phones)
- Wireguard as the client for Linux systems
Clients are also available for Windows, macOS, iOS, and Android.
The concept:
- On the internet, anyone can reach any internet box and thus any exposed server.
- Your server is on your local network. It is accessible only locally unless services are explicitly exposed (as we did with Dockge). To access non-exposed resources, you must be on the same local network.
- We want to securely access these unexposed services (like SSH) from anywhere.
- We also want to connect services between servers, like linking two Dockge instances securely.
To achieve this, weβll create a Virtual Private Network (VPN), i.e., a secure tunnel that only connected machines can use. Theyβll appear to be on the same private network.
Additionally, you can add your phone, laptop, or other devices to the VPN and securely access your server resources wherever you are.
In this diagram, machine 1 is part of two networks:
- Its local network (devices behind the same router, e.g.
192.168.x.x
β machines 1 and 2) - The VPN network (VPN devices with a second IP, e.g.
10.8.x.x
β machines 1 and 4)
You can allow VPN clients to share access to their local networks, but we wonβt do that here for security and subnet conflict reasons (e.g., if two remote machines use the same local IP like 192.168.1.1
).
So only VPN-connected devices can communicate with each other on the VPN, not with other local devices outside the VPN.
Server Side
- Ensure port
51820 UDP
is available and properly forwarded through your router to the server (Source 51820 UDP -> Destination 51820 UDP -> Server
). - Ensure port
51821 TCP
is available for the web UI.
- Warning: This guide uses version
14
of wg-easy. Version15
introduces breaking changes incompatible with this configuration.
Folder structure:
root
βββ docker
βββ wg-easy
βββ config
β βββ etc_wireguard
βββ compose.yaml
βββ .env
The container runs in HOST
mode, meaning it uses the hostβs network stack directly.
Open Dockge, click compose
, and name the stack wg_easy
.
Paste the following configuration:
---
volumes:
etc_wireguard:
services:
wg-easy:
network_mode: host
env_file:
- .env
environment:
- LANG=en
- WG_HOST=${HOST}
- PASSWORD_HASH=${PW}
- WG_DEFAULT_ADDRESS=${ADDRESS}
- WG_HIDE_KEYS=never
- WG_ALLOWED_IPS=${IPS}
- WG_DEFAULT_DNS=
- UI_TRAFFIC_STATS=true
- UI_CHART_TYPE=1
image: ghcr.io/wg-easy/wg-easy:14
container_name: wg-easy
volumes:
- /docker/wg_easy/config/etc_wireguard:/etc/wireguard
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
services
wg-easy:
#...
labels:
- com.centurylinklabs.watchtower.enable=true
In .env
:
HOST=
PW=
ADDRESS=
IPS=
Variable | Description | Example |
---|---|---|
HOST | Domain name of the host | mydomain.com |
PW | Bcrypt password hash, generate here. NOTE: Double the $ characters | $$2a$$12$$FF6T4QqSP9Ho |
ADDRESS | VPN DHCP address range, the x must remain, others can vary | 10.8.0.x |
IPS | IPs routed by clients through the VPN. Use 10.8.0.0/24 to only route VPN traffic. To include local LAN, add 192.168.0.0/16 separated by commas. | 10.8.0.0/24 |
Deploy the stack.
Enable Forwarding on Host
To allow communication between VPN clients, enable:
sudo sysctl net.ipv4.ip_forward=1
sudo sysctl net.ipv4.conf.all.src_valid_mark=1
Retrieve Configuration Files
To configure clients, download the config files from the server:
- Visit
http://your-server-ip:51821
- Create a client
- Download the config file
- Rename it to
wg0.conf
- If it fails, check firewall rules.
On the Client Server
- Assumes the client is a Linux server with Docker installed
Folder structure:
root
βββ docker
βββ wireguard
βββ config
β βββ wg_confs
βββ compose.yaml
Create the folder /docker/wireguard/config/wg_confs
:
sudo mkdir -p /docker/wireguard/config/wg_confs
Copy the wg0.conf
file downloaded earlier:
/home/youruser
, then move it:sudo cp ~/wg0.conf /docker/wireguard/config/wg_confs
Create compose.yaml
in /docker/wireguard
:
sudo vi /docker/wireguard/compose.yaml
Press i
to enter insert mode and paste:
services:
wireguard:
image: lscr.io/linuxserver/wireguard:latest
container_name: wireguard
network_mode: host
cap_add:
- NET_ADMIN
- SYS_MODULE #optional
environment:
- TZ=Europe/Paris
volumes:
- /docker/wireguard/config:/config
- /lib/modules:/lib/modules #optional
restart: unless-stopped
Press Esc
then type :x
to save and exit.
Start the container:
cd /docker/wireguard
sudo docker compose up -d
- Repeat for each client
Other Devices
- Phone: Install Wireguard and scan the QR code from the web UI (
http://your-server-ip:51821
) - PC: Install the Wireguard client and import the config file
- Warning: If a client device is on the same LAN as the server, edit
wg0.conf
and change the endpoint to the local server IP: Endpoint = your-server-ip:51820
And this is the result: