docker.recipes

WireGuard VPN Server Stack

intermediate

Modern VPN with WireGuard, web UI, and monitoring.

Overview

WireGuard represents a paradigm shift in VPN technology, offering a modern alternative to traditional solutions like OpenVPN and IPsec. Developed by security researcher Jason Donenfeld, WireGuard leverages state-of-the-art cryptography including Curve25519, ChaCha20, and Poly1305 to deliver exceptional performance while maintaining a minimal codebase of just 4,000 lines. This simplicity reduces attack surface and makes security auditing feasible, while achieving speeds 3-4x faster than OpenVPN through its kernel-level implementation. This monitoring-enabled stack combines WireGuard's core VPN capabilities with wg-easy's intuitive web interface, Prometheus metrics collection, and Grafana visualization dashboards. The wg-easy component eliminates WireGuard's traditionally complex configuration process, providing QR code generation for mobile devices and streamlined peer management. Meanwhile, the wireguard-exporter feeds connection metrics, bandwidth usage, and peer statistics into Prometheus, which Grafana transforms into actionable monitoring dashboards for tracking VPN performance and usage patterns. This configuration particularly benefits homelab enthusiasts, small businesses, and development teams who need enterprise-grade VPN monitoring without the complexity of traditional solutions. The stack provides visibility into which peers are connected, bandwidth consumption per client, connection stability metrics, and historical usage patterns - intelligence typically reserved for expensive commercial VPN solutions.

Key Features

  • ChaCha20-Poly1305 authenticated encryption with Curve25519 key exchange
  • Web-based peer management with QR code generation for mobile clients
  • Real-time metrics collection for bandwidth usage and connection statistics
  • Cryptokey routing for automatic peer-to-peer connectivity
  • Mobile roaming support with seamless IP address transitions
  • PromQL-powered analytics for complex VPN usage queries
  • Automatic peer handshake monitoring and connection health tracking
  • Multi-dimensional labeling for per-client bandwidth and uptime analysis

Common Use Cases

  • 1Homelab remote access with usage monitoring and client tracking
  • 2Small office site-to-site connectivity with bandwidth analytics
  • 3Development team secure access to staging environments with audit trails
  • 4IoT device management with per-device connection monitoring
  • 5Remote work infrastructure with employee usage reporting
  • 6Gaming server access with latency and connection quality metrics
  • 7Privacy-focused browsing with data usage tracking and performance monitoring

Prerequisites

  • Minimum 512MB RAM for monitoring stack (256MB WireGuard + 256MB Prometheus/Grafana)
  • UDP port 51820 forwarded through firewall for WireGuard traffic
  • Public IP address or dynamic DNS domain for WG_HOST variable
  • Basic understanding of VPN networking and port forwarding concepts
  • Linux kernel with WireGuard module support (kernel 5.6+ or backport module)
  • Router administrative access for port forwarding configuration

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 wg-easy:
3 image: weejewel/wg-easy:latest
4 environment:
5 - WG_HOST=${WG_HOST}
6 - PASSWORD=${WG_PASSWORD}
7 - WG_PORT=51820
8 - WG_DEFAULT_DNS=1.1.1.1
9 - WG_ALLOWED_IPS=0.0.0.0/0
10 volumes:
11 - wg_data:/etc/wireguard
12 ports:
13 - "51820:51820/udp"
14 - "51821:51821/tcp"
15 cap_add:
16 - NET_ADMIN
17 - SYS_MODULE
18 sysctls:
19 - net.ipv4.ip_forward=1
20 - net.ipv4.conf.all.src_valid_mark=1
21 networks:
22 - wg_net
23
24 wireguard-exporter:
25 image: mindflavor/prometheus-wireguard-exporter:latest
26 cap_add:
27 - NET_ADMIN
28 network_mode: host
29 command:
30 - -n
31 - /etc/wireguard/wg0.conf
32 volumes:
33 - wg_data:/etc/wireguard:ro
34
35 prometheus:
36 image: prom/prometheus:latest
37 ports:
38 - "9090:9090"
39 volumes:
40 - ./prometheus.yml:/etc/prometheus/prometheus.yml
41 - prometheus_data:/prometheus
42 networks:
43 - wg_net
44
45 grafana:
46 image: grafana/grafana:latest
47 ports:
48 - "3000:3000"
49 environment:
50 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
51 volumes:
52 - grafana_data:/var/lib/grafana
53 networks:
54 - wg_net
55
56volumes:
57 wg_data:
58 prometheus_data:
59 grafana_data:
60
61networks:
62 wg_net:

.env Template

.env
1# WireGuard VPN
2WG_HOST=your.public.ip.or.domain
3WG_PASSWORD=secure_admin_password
4GRAFANA_PASSWORD=secure_grafana_password
5
6# WG-Easy UI at http://localhost:51821
7# VPN port: 51820/UDP

Usage Notes

  1. 1WG-Easy UI at http://localhost:51821
  2. 2VPN connects on port 51820/UDP
  3. 3Download client configs from UI
  4. 4Forward port 51820/UDP on router
  5. 5Set WG_HOST to public IP/domain

Individual Services(4 services)

Copy individual services to mix and match with your existing compose files.

wg-easy
wg-easy:
  image: weejewel/wg-easy:latest
  environment:
    - WG_HOST=${WG_HOST}
    - PASSWORD=${WG_PASSWORD}
    - WG_PORT=51820
    - WG_DEFAULT_DNS=1.1.1.1
    - WG_ALLOWED_IPS=0.0.0.0/0
  volumes:
    - wg_data:/etc/wireguard
  ports:
    - 51820:51820/udp
    - 51821:51821/tcp
  cap_add:
    - NET_ADMIN
    - SYS_MODULE
  sysctls:
    - net.ipv4.ip_forward=1
    - net.ipv4.conf.all.src_valid_mark=1
  networks:
    - wg_net
wireguard-exporter
wireguard-exporter:
  image: mindflavor/prometheus-wireguard-exporter:latest
  cap_add:
    - NET_ADMIN
  network_mode: host
  command:
    - "-n"
    - /etc/wireguard/wg0.conf
  volumes:
    - wg_data:/etc/wireguard:ro
prometheus
prometheus:
  image: prom/prometheus:latest
  ports:
    - "9090:9090"
  volumes:
    - ./prometheus.yml:/etc/prometheus/prometheus.yml
    - prometheus_data:/prometheus
  networks:
    - wg_net
grafana
grafana:
  image: grafana/grafana:latest
  ports:
    - "3000:3000"
  environment:
    - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
  volumes:
    - grafana_data:/var/lib/grafana
  networks:
    - wg_net

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 wg-easy:
5 image: weejewel/wg-easy:latest
6 environment:
7 - WG_HOST=${WG_HOST}
8 - PASSWORD=${WG_PASSWORD}
9 - WG_PORT=51820
10 - WG_DEFAULT_DNS=1.1.1.1
11 - WG_ALLOWED_IPS=0.0.0.0/0
12 volumes:
13 - wg_data:/etc/wireguard
14 ports:
15 - "51820:51820/udp"
16 - "51821:51821/tcp"
17 cap_add:
18 - NET_ADMIN
19 - SYS_MODULE
20 sysctls:
21 - net.ipv4.ip_forward=1
22 - net.ipv4.conf.all.src_valid_mark=1
23 networks:
24 - wg_net
25
26 wireguard-exporter:
27 image: mindflavor/prometheus-wireguard-exporter:latest
28 cap_add:
29 - NET_ADMIN
30 network_mode: host
31 command:
32 - -n
33 - /etc/wireguard/wg0.conf
34 volumes:
35 - wg_data:/etc/wireguard:ro
36
37 prometheus:
38 image: prom/prometheus:latest
39 ports:
40 - "9090:9090"
41 volumes:
42 - ./prometheus.yml:/etc/prometheus/prometheus.yml
43 - prometheus_data:/prometheus
44 networks:
45 - wg_net
46
47 grafana:
48 image: grafana/grafana:latest
49 ports:
50 - "3000:3000"
51 environment:
52 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
53 volumes:
54 - grafana_data:/var/lib/grafana
55 networks:
56 - wg_net
57
58volumes:
59 wg_data:
60 prometheus_data:
61 grafana_data:
62
63networks:
64 wg_net:
65EOF
66
67# 2. Create the .env file
68cat > .env << 'EOF'
69# WireGuard VPN
70WG_HOST=your.public.ip.or.domain
71WG_PASSWORD=secure_admin_password
72GRAFANA_PASSWORD=secure_grafana_password
73
74# WG-Easy UI at http://localhost:51821
75# VPN port: 51820/UDP
76EOF
77
78# 3. Start the services
79docker compose up -d
80
81# 4. View logs
82docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/wireguard-vpn-complete/run | bash

Troubleshooting

  • Clients can't connect after setup: Verify WG_HOST matches your actual public IP or DDNS hostname exactly
  • wireguard-exporter shows no metrics: Ensure /etc/wireguard/wg0.conf exists and has proper permissions for container access
  • High memory usage in Prometheus: Reduce retention period or increase --storage.tsdb.retention.time to manage data retention
  • wg-easy UI inaccessible: Check that port 51821 isn't blocked by host firewall and container has proper NET_ADMIN capabilities
  • Peers lose connection frequently: Verify net.ipv4.ip_forward=1 sysctl is applied and not overridden by host networking
  • Grafana dashboards empty: Confirm prometheus.yml targets include wireguard-exporter:9586 and Prometheus can scrape metrics

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space