speedtest.it
← Blog

Step-by-step guide to installing and configuring a WireGuard server on Debian 12: packages, key generation, peer configuration, and firewall rules explained.


WireGuard is today one of the most appreciated VPN protocols: fast, secure, and surprisingly simple to configure compared to veterans like OpenVPN. In this guide we install a WireGuard server on Debian 12 (Bookworm) using wg-easy, a web interface that makes client management very easy even without the command line. At the end you will have a working personal VPN, accessible from any device.

What you need

  • A working Debian 12 server (VPS, dedicated server, or local machine)
  • Root access or a user with sudo privileges
  • A static public IP or a domain pointing to the server
  • Ports 51820/UDP (WireGuard) and 51821/TCP (wg-easy web interface) open in the firewall

If you have a VPS, verify that the provider's firewall (not just the system one) allows these ports.

Step 1: update the system

Before installing anything, bring the system up to the latest version:

sudo apt update && sudo apt upgrade -y

Reboot if there are kernel updates:

sudo reboot

Step 2: install Docker

wg-easy runs inside a Docker container, so we need to install it first:

sudo apt install -y docker.io docker-compose

Verify that Docker is active:

sudo systemctl enable --now docker
sudo docker --version

Step 3: install WireGuard and qrencode

Even though wg-easy manages everything via Docker, it's useful to have the native WireGuard tools for debugging:

sudo apt install -y wireguard wireguard-tools qrencode

Step 4: generate the password hash for wg-easy

wg-easy requires a password for the web interface. For security it doesn't save it in plaintext but in bcrypt hash format. Generate the hash with this command (replace yourpassword with the password you want to use):

docker run --rm -it ghcr.io/wg-easy/wg-easy wgpwcp yourpassword

The command will return something like:

$2b$12$abc123...xyz

Copy this value: you'll need it in the next step.

Step 5: create the directory and docker-compose.yml file

mkdir -p ~/wireguard && cd ~/wireguard
nano docker-compose.yml

Paste this configuration, replacing the values between <angle brackets>:

version: "3.8"
services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy
    container_name: wg-easy
    environment:
      - WG_HOST=<server-ip-or-domain>
      - PASSWORD_HASH=<hash-generated-in-step-4>
      - WG_DEFAULT_DNS=1.1.1.1,8.8.8.8
      - WG_ALLOWED_IPS=0.0.0.0/0,::/0
    volumes:
      - ~/.wg-easy:/etc/wireguard
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv4.ip_forward=1
    restart: unless-stopped

For WG_HOST use the server's public IP address or your domain (e.g., vpn.mydomain.com). For PASSWORD_HASH paste the hash generated earlier — note: if the hash contains $, you must enclose the value in single quotes in the YAML.

Step 6: start wg-easy

sudo docker compose up -d

Verify that the container is running:

sudo docker ps

You should see wg-easy in the list with status Up.

Step 7: access the web interface

Open your browser and go to:

http://<server-ip>:51821

Enter the password you chose in step 4 (not the hash, the original password).

Step 8: add your clients

From the web interface:

  1. Click "+ New"
  2. Assign a name to the client (e.g., "iPhone Francesco", "Work Laptop")
  3. Click "Create"

The server automatically generates the key pair and configuration. You have two ways to configure the client:

  • QR code: scan it with the WireGuard app on iOS or Android
  • .conf file: download it and import it into the WireGuard client on PC (Windows, macOS, Linux)

Step 9: configure the client

Smartphone (iOS / Android):

  1. Install the WireGuard app from the App Store or Google Play
  2. Tap + and choose "Scan QR code"
  3. Point the camera at the QR code shown by wg-easy

PC (Windows / macOS / Linux):

  1. Download WireGuard from wireguard.com
  2. Import the .conf file downloaded from the web interface
  3. Activate the tunnel

Step 10: verify the connection

Once connected, visit My IP to verify that the IP address shown is that of your VPN server, not your real IP. If it is, the VPN is working correctly.

Security: things to do after installation

  • Don't expose port 51821 to the internet: consider putting it behind a reverse proxy with authentication (Nginx + HTTP Basic Auth) or accessing it only through the VPN itself
  • Update regularly: sudo docker compose pull && sudo docker compose up -d
  • Back up your keys: the ~/.wg-easy directory contains the complete configuration; back it up in a safe place
  • Host firewall: configure ufw to restrict access to only the necessary ports

Frequently asked questions

How many clients can I add? There is no technical limit imposed by wg-easy. The practical limit is the server's bandwidth: every client browsing through the VPN uses the server's bandwidth.

What happens if the server restarts? The container has restart: unless-stopped, so it automatically restarts with Docker. Configurations persist in the volume mounted at ~/.wg-easy.

Can I use wg-easy with a domain instead of an IP? Yes, and it's actually recommended if your IP is dynamic. Configure a DNS A record pointing to the server and use the domain in WG_HOST. If the IP changes, only update the DNS.


← All articles