Build Your own VPN with WireGuard and AWS Lightsail (2025)
the complete guide from zero to hero
Recently, my Starlink plan dropped support for a static public IP. Sad days. I sought to find the cheapest way to run a VPN on AWS. Turns out its pretty easy, so I wrote a guide.
As a note, the instance I am using costs $7 per month but I could have gotten away with $5 per month. That’s a pretty small price even if it might not be “the absolute cheapest” way to get a static public IP.
WireGuard is a modern, fast, and secure VPN protocol that's incredibly easy to set up. AWS Lightsail is Amazon's simplified cloud hosting service designed for developers, small businesses, and anyone who wants to get started with AWS without the complexity of the full AWS ecosystem.
Prerequisites
An AWS account
Basic familiarity with the command line
A client device (Mac, Windows, iOS, Android, etc.)
Step 1: Create an AWS Lightsail Instance
Log into AWS Lightsail and click "Create instance"
Choose your instance location - Pick a region close to where you'll be using the VPN most often
Select the platform - Choose "Linux/Unix"
Choose a blueprint - Select "Ubuntu 24.04 LTS"
Choose your instance plan - The $5/month plan (1 GB RAM, 1 vCPU) is sufficient for most personal use
Name your instance - Something like "wireguard-vpn"
Create the instance and wait for it to start
Step 2: Configure the Firewall
In Lightsail, go to your instance's "Networking" tab
Add a custom firewall rule:
Application: Custom
Protocol: UDP
Port: 51820 (WireGuard's default port)
Ensure SSH (port 22) is also allowed for administration
Step 3: Connect to Your Server and Install WireGuard
Connect via SSH using Lightsail's browser-based SSH or your preferred SSH client
Update the system:
sudo apt update && sudo apt upgrade -yInstall WireGuard:
sudo apt install wireguard -yStep 4: Generate Keys
Create a directory for WireGuard:
sudo mkdir -p /etc/wireguard
cd /etc/wireguardGenerate server keys:
# Generate private key
sudo wg genkey | sudo tee server_private.key
# Generate public key from private key
sudo cat server_private.key | wg pubkey | sudo tee server_public.key
# Set proper permissions
sudo chmod 600 server_private.keyGenerate client keys:
# Generate client private key
sudo wg genkey | sudo tee client_private.key
# Generate client public key
sudo cat client_private.key | wg pubkey | sudo tee client_public.key
# Set proper permissions
sudo chmod 600 client_private.keyStep 5: Configure the WireGuard Server
Find your server's network interface:
ip route | grep defaultLook for the interface name (usually
ens5on AWS)Create the server configuration:
sudo nano /etc/wireguard/wg0.confAdd the following configuration (replace the keys with your generated keys):
[Interface]
Address = 10.0.0.1/24
SaveConfig = true
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens5 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens5 -j MASQUERADE
ListenPort = 51820
PrivateKey = [YOUR_SERVER_PRIVATE_KEY]
[Peer]
PublicKey = [YOUR_CLIENT_PUBLIC_KEY]
AllowedIPs = 10.0.0.2/32Replace the placeholders:
Replace
[YOUR_SERVER_PRIVATE_KEY]with the contents ofserver_private.keyReplace
[YOUR_CLIENT_PUBLIC_KEY]with the contents ofclient_public.keyChange
ens5to your server's network interface if different
Step 6: Enable IP Forwarding
Enable IP forwarding:
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -pStep 7: Start WireGuard
Enable and start the WireGuard service:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0Check the status:
sudo systemctl status wg-quick@wg0Verify the interface is running:
sudo wg showStep 8: Create Client Configuration
Get your server's public IP:
curl ifconfig.meCreate a client configuration file on your local machine (save as
wg0-client.conf):
[Interface]
PrivateKey = [YOUR_CLIENT_PRIVATE_KEY]
Address = 10.0.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = [YOUR_SERVER_PUBLIC_KEY]
Endpoint = [YOUR_SERVER_PUBLIC_IP]:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25Replace the placeholders:
Replace
[YOUR_CLIENT_PRIVATE_KEY]with the contents ofclient_private.keyReplace
[YOUR_SERVER_PUBLIC_KEY]with the contents ofserver_public.keyReplace
[YOUR_SERVER_PUBLIC_IP]with your server's public IP
Step 9: Install WireGuard Client
For Mac (Recommended: Homebrew)
Option 1: Using Homebrew (Command Line)
# Install WireGuard tools
brew install wireguard-tools
# Import your config file
sudo wg-quick up wg0-client.confOption 2: Using the Mac App Store Download the official WireGuard app from the Mac App Store for a GUI interface.
PAUSE: Why choose Homebrew?
Command-line control for advanced users
Easy to script and automate
Direct integration with macOS networking
Better for managing multiple VPN configs
For Other Platforms
For Windows/iOS/Android: Download the official WireGuard app from the respective app stores.
For Linux:
sudo apt install wireguardStep 10: Connect and Test
Import the client configuration into your WireGuard client app
Connect to the VPN
Test your connection:
# Check your public IP (should show your server's IP)
curl ifconfig.me
# Test DNS resolution
nslookup google.comAdding More Clients
To add additional clients:
Generate new keys for each client:
sudo wg genkey | sudo tee client2_private.key
sudo cat client2_private.key | wg pubkey | sudo tee client2_public.keyAdd new peer to server config:
sudo nano /etc/wireguard/wg0.confAdd another
[Peer]section:
[Peer]
PublicKey = [CLIENT2_PUBLIC_KEY]
AllowedIPs = 10.0.0.3/32Restart WireGuard:
sudo systemctl restart wg-quick@wg0Security Best Practices
Use strong, unique keys for each client
Regularly rotate keys (monthly or quarterly)
Monitor connection logs:
sudo journalctl -u wg-quick@wg0 -fKeep your server updated:
sudo apt update && sudo apt upgradeConsider using a firewall like
ufwfor additional securityBack up your keys securely
Troubleshooting
VPN connects but no internet:
Check if IP forwarding is enabled:
cat /proc/sys/net/ipv4/ip_forwardVerify iptables rules:
sudo iptables -t nat -L
Connection fails:
Check firewall rules in AWS Lightsail
Verify the server's public IP in client config
Check WireGuard service status:
sudo systemctl status wg-quick@wg0
DNS not working:
Try different DNS servers in client config (8.8.8.8, 1.1.1.1, 9.9.9.9)
Other things to note:
I installed ControlD on the server to handle DNS. I also added some cool aliases in my terminal:
echo '
# WireGuard VPN
alias vpn-on="sudo /opt/homebrew/bin/wg-quick up wg0"
alias vpn-off="sudo /opt/homebrew/bin/wg-quick down wg0; dns-reset"
alias vpn-kill="sudo pkill -f wg-quick; sudo pkill -f wireguard-go; dns-reset"
alias vpn-status="sudo wg show"
alias vpn-ip="curl -s ifconfig.io"
' >> ~/.zshrc
source ~/.zshrcAnd that’s that.
Cheers,
Joe



