Welcome to the WireGuard VPN Server Setup repository! This provides a simple and secure WireGuard VPN deployment using Docker Compose, Uncomplicated Firewall (UFW), IPTables, and Network Address Translation (NAT) for persistent, secure VPN access.
- WireGuard VPN with Web UI: Deploys WireGuard using the wg-easy Docker image, which provides an intuitive web-based VPN management interface
- Customizable Deployment: Production-ready
docker-compose.yamlwith an optional development mode for testing (FUTURE) - Secure Config Management: Uses a
.envfile to protect sensitive data like public IP, ports and password credentials - Firewall & NAT Hardening: Implements secure firewall rule to ensure safe VPN traffic routing
- Dockerized & Portable: Runs in a containerized environment for easy setup and scalability
- Automatic Persistence: Ensures the WireGuard VPN server and firewall settings survive reboots
- A host machine with a kernel that supports WireGuard (all modern Linux kernels)
- A host machine with Docker & Docker Compose installed
- A router configured with NAT/port forwarding for external VPN access
git clone https://github.com/bkaewell/wireguard-setup.git
cd wireguard-setupCopy the example .env file and configure your WireGuard VPN server:
cp .env.example .env| Variable | Description |
|---|---|
WG_SERVER_PUBLIC_IP |
Your public IP address or domain |
WG_SERVER_HOSTNAME |
Your serverβs hostname (optional) |
WG_SERVER_PORT |
WireGuard VPN listening port (default: 51820/UDP) |
WG_WEB_UI_PORT |
WireGuard Web UI access port (default: 51821/TCP) |
WG_WEB_UI_PASSWORD |
Set a secure admin password for the WireGuard Web UI |
π₯π₯ Storing all config values in
.envkeepsdocker-compose.yamlcleaner, more maintainable, and easily customizable. To override settings, modifydocker-compose.yamldirectly, but using.envensures modular/consistent updates across deployments while keeping private data out of version control (GitHub)
To allow VPN traffic, open the configured ports (WG_SERVER_PORT & WG_WEB_UI_PORT) in UFW:
sudo ufw allow <WG_SERVER_PORT>/udp
sudo ufw allow <WG_WEB_UI_PORT>/tcpOptional: Restrict WireGuard Web UI access to a specific trusted IP:
sudo ufw allow from <YOUR_TRUSTED_IP> to any port <WG_WEB_UI_PORT> proto tcpTo enable remote access to WireGuard, you must:
- Assign a static local IP to the WireGuard VPN server
- Set up port forwarding on your router to ensure VPN traffic reaches the WireGuard VPN server
Log into your router's admin panel
| Router Model | Admin Panel URL |
|---|---|
| TP-Link A7 | http://192.168.0.1 |
| Other Routers | http://192.168.X.1 |
For TP-Link A7 Routers:
- Go to Advanced > Network > DHCP Server > Settings > Address Reservation
- Click Add and select the MAC address of the WireGuard VPN server
- Assign it an available static IP (i.e.
192.168.0.123) - Save and reboot the router
π₯π₯ A static local IP (
192.168.0.123) ensures that port forwarding always routes VPN traffic correctly
For TP-Link A7 Routers:
- Navigate to Advanced > NAT Forwarding > Virtual Servers
- Click Add and enter the following values (Save/reboot the router):
| Service Name | External Port | Internal Port | Protocol | Purpose | Internal IP Address |
|---|---|---|---|---|---|
| WireGuard VPN Server | <WG_SERVER_PORT> |
<WG_SERVER_PORT> |
UDP | Handles VPN client connections | 192.168.0.123 |
| Web UI for WireGuard | <WG_WEB_UI_PORT> |
<WG_WEB_UI_PORT> |
TCP | Manage VPN clients and settings | 192.168.0.123 |
| SSH Access | 22 | 22 | TCP | Remote access to the host machine | 192.168.0.123 |
π₯π₯ Now, external devices can securely connect to WireGuard using your public IP or domain, ensuring seamless remote access
| Test Type | Command | Protocol | Expected Behavior | Use Case |
|---|---|---|---|---|
| UDP Connectivity | nc -uzv <IP> <PORT> |
UDP | β "Connection succeeded" if port is open | Check if a UDP port is accessible |
| TCP Connectivity | nc -zv <IP> <PORT> |
TCP | β "Connection succeeded" if port is open | Verify if a TCP port is accepting connections |
| Check Listening Ports on Server | sudo ss -tulnp | grep <PORT> |
TCP/UDP | Shows process listening if port is open | Confirm if WireGuard or a service is running on the port |
| Check Firewall Rules (UFW) | sudo ufw status verbose | grep <PORT> |
TCP/UDP | Displays if port is allowed | Verify firewall settings for the port |
| Check Firewall Rules (IPTables) | sudo iptables -L -v -n | grep <PORT> |
TCP/UDP | Shows port rules if configured | Ensure IPTables isnβt blocking traffic |
| Capture Incoming Packets (UDP/TCP) | sudo tcpdump -i any port <PORT> -n |
TCP/UDP | Shows real-time packets if traffic is reaching the server | Troubleshoot whether packets are arriving |
This project requires Docker and Docker Compose. Choose your installation method based on your operating system:
brew install --cask dockerNote: Docker Desktop must be running in the background for docker commands to work
- You can launch it from Applications > Docker or run
open -a Docker
sudo apt update
sudo apt install -y docker.io docker-composedocker --version
docker-compose --versionsudo usermod -aG docker ${USER:-$(whoami)}
newgrp dockersudo systemctl enable --now dockerUse Docker Compose to start the containerized wg-easy service, which includes both the WireGuard VPN server and its web-based management interface. The service runs in detached mode (in the background):
docker compose up -d # Start in production mode
docker compose --profile prod up -d # (Optional) Future dev profile supportVerify the container is running:
docker ps -aYou should see the wg-easy container running
docker compose downThis stops the entire VPN stack and removes the running container, but retains volumes and configs for future startups
Once deployed, access the wg-easy web interface through:
http://<WG_SERVER_PUBLIC_IP>:<WG_WEB_UI_PORT>
To log in, enter the bcrypt-hashed admin password you configured in the WG_WEB_UI_PASSWORD environment variable inside your .env file. Make sure the following conditions are met for successful access:
- Your router must have port <WG_WEB_UI_PORT>/TCP forwarded to your server's internal IP (
192.168.0.123) - The
wg-easyDocker container must be actively running on the WireGuard VPN server
π₯π₯ This web interface allows you to manage VPN clients, generate configuration files, and monitor your WireGuard setup from any browser
wireguard-setup/ # Root directory for WireGuard VPN Server setup
βββ config/ # Stores WireGuard configuration files
βββ wg0.conf # Auto-generated configuration for the core WireGuard VPN server (ignored in Git)
| # - Contains private keys, server settings, and VPN peer configurations
βββ wg0.json # Web UI backup file for restoring VPN settings (ignored in Git)
| # - Used for restoring server/client settings via the Web UI
βββ docs/ # Documentation for additional setups
βββ firestick_client_setup.md # Guide for configuring WireGuard on Amazon Firestick
βββ wireguard_basics.md # WireGuard overview with a full-tunnel real-world example
βββ scripts/ # Utility scripts for system checks
βββ check_firewall.sh # Firewall & IPTables verification script
βββ check_docker_reboot.sh # Docker restart verification script
βββ docker-compose.yaml # Supports production deployment (Dev mode: FUTURE)
βββ Dockerfile.dev # Builds custom dev-friendly image (FUTURE)
βββ docker-entrypoint.dev.sh # Optional custom entrypoint for dev mode (FUTURE)
βββ .env.example # Template for environment variables
βββ .gitignore # Ignores sensitive files
βββ README.md # Documentation (this file)
- WireGuard Basics β Learn about WireGuard, VPNs, and how they work
- Setup WireGuard on Amazon Firestick
π― Looking to contribute? Open an issue or fork the repo!
π¨βπ» Author: Brian Kaewell
π§ Contact: Please open an issue here