WireGuard Easy with UI
Easy WireGuard VPN setup with web-based management interface and QR code generation.
Overview
WireGuard Easy (wg-easy) is a simplified management interface for WireGuard VPN that eliminates the complexity of traditional VPN server administration. Created to address WireGuard's command-line complexity, wg-easy provides a web-based dashboard for managing VPN clients, generating configuration files, and creating QR codes for mobile device setup. The project transforms WireGuard's powerful but technical foundation into an accessible solution for users who need VPN functionality without extensive networking expertise. This stack combines wg-easy with NGINX to create a production-ready VPN solution with enhanced security and traffic management. NGINX serves as a reverse proxy, providing SSL termination, rate limiting, and additional security layers for the wg-easy web interface. The combination addresses common VPN deployment challenges including certificate management, traffic routing, and client onboarding through QR codes. Organizations benefit from this pairing because NGINX handles the web traffic complexities while wg-easy manages VPN client lifecycle, creating a robust solution that scales from personal use to enterprise deployments. This configuration suits network administrators seeking modern VPN infrastructure, remote teams requiring secure connectivity, and organizations transitioning from legacy VPN solutions to WireGuard's superior performance and security model.
Key Features
- Interactive web dashboard for WireGuard client management with real-time connection status
- Automatic QR code generation for instant mobile client configuration
- One-click client creation and deletion with automatic key pair generation
- Real-time bandwidth monitoring and connection statistics per client
- NGINX reverse proxy with SSL/TLS termination and security headers
- Built-in DNS configuration management for VPN clients
- Automatic IP address allocation within defined subnets
- Password-protected web interface with bcrypt hash authentication
Common Use Cases
- 1Remote work infrastructure for distributed teams needing secure office network access
- 2Homelab enthusiasts creating personal VPN servers for secure internet browsing
- 3Small business secure connectivity for employees accessing internal resources
- 4Development teams requiring secure connections to staging and production environments
- 5Educational institutions providing VPN access for students and faculty
- 6Content creators and digital nomads needing geo-location flexibility
- 7Organizations migrating from expensive commercial VPN solutions to self-hosted alternatives
Prerequisites
- Server with public IP address and UDP port 51820 accessible from internet
- Minimum 512MB RAM recommended for concurrent client connections
- Domain name or static IP for WG_HOST environment variable configuration
- Basic understanding of VPN networking concepts and subnet configuration
- SSL certificate files if enabling HTTPS through NGINX reverse proxy
- Administrative access to router/firewall 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: ghcr.io/wg-easy/wg-easy:latest4 environment: 5 WG_HOST: ${WG_HOST}6 PASSWORD_HASH: ${PASSWORD_HASH}7 WG_DEFAULT_ADDRESS: ${WG_DEFAULT_ADDRESS}8 WG_DEFAULT_DNS: ${WG_DEFAULT_DNS}9 WG_ALLOWED_IPS: ${WG_ALLOWED_IPS}10 ports: 11 - "51820:51820/udp"12 - "51821:51821/tcp"13 volumes: 14 - wg-easy:/etc/wireguard15 cap_add: 16 - NET_ADMIN17 - SYS_MODULE18 sysctls: 19 - net.ipv4.ip_forward=120 - net.ipv4.conf.all.src_valid_mark=121 networks: 22 - vpn-net23 restart: unless-stopped2425 nginx: 26 image: nginx:alpine27 ports: 28 - "80:80"29 - "443:443"30 volumes: 31 - ./nginx.conf:/etc/nginx/nginx.conf:ro32 - ./certs:/etc/nginx/certs:ro33 depends_on: 34 - wg-easy35 networks: 36 - vpn-net37 restart: unless-stopped3839volumes: 40 wg-easy: 4142networks: 43 vpn-net: 44 driver: bridge.env Template
.env
1# WireGuard Host (public IP or domain)2WG_HOST=vpn.example.com34# Password Hash (generate with: wgpw YOUR_PASSWORD)5PASSWORD_HASH=67# Client Configuration8WG_DEFAULT_ADDRESS=10.8.0.x9WG_DEFAULT_DNS=1.1.1.110WG_ALLOWED_IPS=0.0.0.0/0, ::/0Usage Notes
- 1Web UI at http://localhost:51821
- 2Generate QR codes for mobile clients
- 3Port 51820/UDP must be accessible from internet
- 4Use wgpw command to generate password hash
Individual Services(2 services)
Copy individual services to mix and match with your existing compose files.
wg-easy
wg-easy:
image: ghcr.io/wg-easy/wg-easy:latest
environment:
WG_HOST: ${WG_HOST}
PASSWORD_HASH: ${PASSWORD_HASH}
WG_DEFAULT_ADDRESS: ${WG_DEFAULT_ADDRESS}
WG_DEFAULT_DNS: ${WG_DEFAULT_DNS}
WG_ALLOWED_IPS: ${WG_ALLOWED_IPS}
ports:
- 51820:51820/udp
- 51821:51821/tcp
volumes:
- wg-easy:/etc/wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
networks:
- vpn-net
restart: unless-stopped
nginx
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- wg-easy
networks:
- vpn-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 wg-easy:5 image: ghcr.io/wg-easy/wg-easy:latest6 environment:7 WG_HOST: ${WG_HOST}8 PASSWORD_HASH: ${PASSWORD_HASH}9 WG_DEFAULT_ADDRESS: ${WG_DEFAULT_ADDRESS}10 WG_DEFAULT_DNS: ${WG_DEFAULT_DNS}11 WG_ALLOWED_IPS: ${WG_ALLOWED_IPS}12 ports:13 - "51820:51820/udp"14 - "51821:51821/tcp"15 volumes:16 - wg-easy:/etc/wireguard17 cap_add:18 - NET_ADMIN19 - SYS_MODULE20 sysctls:21 - net.ipv4.ip_forward=122 - net.ipv4.conf.all.src_valid_mark=123 networks:24 - vpn-net25 restart: unless-stopped2627 nginx:28 image: nginx:alpine29 ports:30 - "80:80"31 - "443:443"32 volumes:33 - ./nginx.conf:/etc/nginx/nginx.conf:ro34 - ./certs:/etc/nginx/certs:ro35 depends_on:36 - wg-easy37 networks:38 - vpn-net39 restart: unless-stopped4041volumes:42 wg-easy:4344networks:45 vpn-net:46 driver: bridge47EOF4849# 2. Create the .env file50cat > .env << 'EOF'51# WireGuard Host (public IP or domain)52WG_HOST=vpn.example.com5354# Password Hash (generate with: wgpw YOUR_PASSWORD)55PASSWORD_HASH=5657# Client Configuration58WG_DEFAULT_ADDRESS=10.8.0.x59WG_DEFAULT_DNS=1.1.1.160WG_ALLOWED_IPS=0.0.0.0/0, ::/061EOF6263# 3. Start the services64docker compose up -d6566# 4. View logs67docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/wireguard-easy-stack/run | bashTroubleshooting
- wg-easy container fails to start with 'Operation not permitted': Ensure Docker has NET_ADMIN and SYS_MODULE capabilities enabled on host system
- Clients can connect but cannot access internet: Verify net.ipv4.ip_forward=1 sysctl setting and check server firewall rules for IP masquerading
- Web interface shows 'Incorrect password' with correct credentials: Regenerate PASSWORD_HASH using bcrypt and ensure no trailing whitespace in environment variable
- QR codes not generating or displaying blank: Check that WG_HOST environment variable contains externally accessible IP or domain name
- VPN clients connect but have no internet access: Verify WG_DEFAULT_DNS is set to accessible DNS servers like 1.1.1.1 or 8.8.8.8
- NGINX proxy returns 502 Bad Gateway: Ensure wg-easy service is running and accessible on port 51821 within Docker network
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
Shortcuts: C CopyF FavoriteD Download