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 -y
Install WireGuard:
sudo apt install wireguard -y
Step 4: Generate Keys
Create a directory for WireGuard:
sudo mkdir -p /etc/wireguard
cd /etc/wireguard
Generate 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.key
Generate 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.key
Step 5: Configure the WireGuard Server
Find your server's network interface:
ip route | grep default
Look for the interface name (usually
ens5
on AWS)Create the server configuration:
sudo nano /etc/wireguard/wg0.conf
Add 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/32
Replace the placeholders:
Replace
[YOUR_SERVER_PRIVATE_KEY]
with the contents ofserver_private.key
Replace
[YOUR_CLIENT_PUBLIC_KEY]
with the contents ofclient_public.key
Change
ens5
to 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 -p
Step 7: Start WireGuard
Enable and start the WireGuard service:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
Check the status:
sudo systemctl status wg-quick@wg0
Verify the interface is running:
sudo wg show
Step 8: Create Client Configuration
Get your server's public IP:
curl ifconfig.me
Create 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 = 25
Replace the placeholders:
Replace
[YOUR_CLIENT_PRIVATE_KEY]
with the contents ofclient_private.key
Replace
[YOUR_SERVER_PUBLIC_KEY]
with the contents ofserver_public.key
Replace
[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.conf
Option 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 wireguard
Step 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.com
Adding 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.key
Add new peer to server config:
sudo nano /etc/wireguard/wg0.conf
Add another
[Peer]
section:
[Peer]
PublicKey = [CLIENT2_PUBLIC_KEY]
AllowedIPs = 10.0.0.3/32
Restart WireGuard:
sudo systemctl restart wg-quick@wg0
Security Best Practices
Use strong, unique keys for each client
Regularly rotate keys (monthly or quarterly)
Monitor connection logs:
sudo journalctl -u wg-quick@wg0 -f
Keep your server updated:
sudo apt update && sudo apt upgrade
Consider using a firewall like
ufw
for additional securityBack up your keys securely
Troubleshooting
VPN connects but no internet:
Check if IP forwarding is enabled:
cat /proc/sys/net/ipv4/ip_forward
Verify 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 ~/.zshrc
And that’s that.
Cheers,
Joe