This Terraform configuration automatically deploys a WireGuard VPN server on AWS EC2 with a web-based management interface.
- π One-command deployment of WireGuard VPN server
- π§ Web-based management interface (wg-easy)
- π‘οΈ Secure by default with proper security groups
- π° Cost-optimized using t3.nano instances
- π Multi-region support - deploy anywhere
- π± 20 peer configurations ready out of the box
- π Elastic IP for consistent connection
- AWS CLI configured with appropriate permissions
- Terraform installed (>= 1.0)
- SSH key pair created in your target AWS region (see setup below)
macOS:
brew install terraformUbuntu/Debian:
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraformWindows: Download from terraform.io
You need to create SSH key pairs manually in each region where you plan to deploy.
- Go to AWS Console β EC2 β Key Pairs
- Select your target region (top-right corner)
- Click "Create key pair"
- Name:
wireguard-key(or any name you prefer) - Key pair type: RSA
- Private key file format: .pem
- Click "Create key pair"
- Download and save the .pem file securely
- Set permissions:
chmod 400 ~/path/to/your-key.pem
Repeat for each region you plan to use (same name, different regions).
If you already have key pairs in some regions, just note their names. Terraform will prompt you for the key name during deployment.
Create a new directory and save all the Terraform files:
mkdir wireguard-terraform
cd wireguard-terraform
# Save all .tf files and user_data.sh in this directoryCopy the example configuration:
cp terraform.tfvars.example terraform.tfvarsEdit terraform.tfvars:
aws_region = "eu-north-1" # Your preferred region
aws_access_key = "your-aws-access-key"
aws_secret_key = "your-aws-secret-key"
ssh_key_name = "wireguard-key" # Your SSH key name in AWS
instance_name = "My VPN Server" # Name for your EC2 instanceImportant: Make sure the ssh_key_name exists in your selected aws_region!
# Initialize Terraform
terraform init
# Review the deployment plan
terraform plan
# Deploy the infrastructure
terraform applyType yes when prompted to confirm the deployment.
After deployment (takes ~3-5 minutes), Terraform will output:
wireguard_web_ui_url = "http://1.2.3.4:51821"
ssh_connection_command = "ssh -i ~/.ssh/my-key-pair.pem [email protected]"
Visit the web UI URL to manage your WireGuard VPN!

Once your VPN server is running, you can connect from any device using WireGuard clients. Here's how to set up each platform:
- Install WireGuard app from Google Play Store
- Open the app and tap the "+" button
- Scan QR Code:
- Go to your web UI:
http://YOUR_IP:51821 - Find your device in the peer list
- Tap the QR code icon
- Scan with your phone
- Go to your web UI:
- Give it a name (e.g., "My Phone") and tap "Create Tunnel"
- Connect by toggling the switch
- Install WireGuard app from App Store
- Open the app and tap "Add a tunnel"
- Scan QR Code:
- Go to your web UI:
http://YOUR_IP:51821 - Find your device in the peer list
- Tap the QR code icon
- Scan with your iPhone
- Go to your web UI:
- Give it a name and tap "Save"
- Connect by toggling the switch
- Download WireGuard from wireguard.com/install
- Install and run WireGuard
- Get config file:
- Go to your web UI:
http://YOUR_IP:51821 - Find your device in the peer list
- Click the download icon to get
.conffile
- Go to your web UI:
- Import config: Click "Add Tunnel" β "Import tunnel(s) from file"
- Select your downloaded
.conffile - Connect by clicking "Activate"
- Install WireGuard from Mac App Store or download from wireguard.com
- Open WireGuard application
- Get config file from your web UI (same as Windows above)
- Import: Click "+" β "Import tunnel(s) from file"
- Select your
.conffile and click "Import" - Connect by toggling the switch
- URL:
http://YOUR_IP:51821 - Default: No password required (change this in production!)
ssh -i ~/.ssh/your-key.pem ubuntu@YOUR_IP# On the server
cd wireguard
docker-compose logs wg-easyEdit main.tf and modify the instance_type:
resource "aws_instance" "wireguard_server" {
instance_type = "t3.small" # Changed from t3.nano
# ...
}Edit the security group in main.tf to restrict access:
# Restrict SSH to your IP only
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["YOUR_IP/32"] # Replace YOUR_IP
description = "SSH from my IP only"
}To enable HTTPS, modify the docker-compose.yml template in user_data.sh:
environment:
- INSECURE=false # Changed from true- Instance: t3.nano (~$3.80/month)
- Storage: 8GB gp3 (~$0.80/month)
- Data Transfer: $0.09/GB outbound
- Elastic IP: Free while attached
Estimated monthly cost: ~$5-15 depending on usage
To destroy all resources:
terraform destroyType yes to confirm. This will delete:
- EC2 instance
- Elastic IP
- Security Group
- All associated resources
1. SSH Key Not Found
Error: InvalidKeyPair.NotFound
Solution:
- Ensure your SSH key exists in the selected region
- Go to AWS Console β EC2 β Key Pairs (in the correct region)
- Create the key pair if it doesn't exist
- Check the key name matches what you entered in terraform.tfvars
2. Wrong Region Selected
Error: collecting instance settings: couldn't find resource
Solution: Make sure your SSH key exists in the region you selected
3. WireGuard Not Starting
# SSH to the server and check
sudo tail -f /var/log/user-data.log
docker-compose logs wg-easy3. Can't Access Web UI
- Check security group allows port 51821
- Verify instance is running:
terraform show - Check if Docker is running:
docker ps
4. Terraform Permission Issues Ensure your AWS user/role has these permissions:
- EC2: Create/modify instances, security groups, elastic IPs
- VPC: Describe VPCs, subnets
- Check the user-data log:
/var/log/user-data.log - Verify Docker status:
systemctl status docker - Check container logs:
docker-compose logs
- Change the default web UI password
- Restrict security group access to known IPs
- Regularly update the Docker image
- Monitor access logs
- Consider enabling AWS CloudTrail
Create separate terraform directories for each region, or use Terraform workspaces:
terraform workspace new us-west-2
terraform workspace new eu-west-1Add this to your configuration for automated snapshots:
# Add to main.tf
resource "aws_ebs_snapshot" "wireguard_backup" {
volume_id = aws_instance.wireguard_server.root_block_device[0].volume_id
description = "WireGuard server backup"
tags = {
Name = "WireGuard Backup"
}
}Happy VPN-ing! π