Setup WireGuard VPN on AWS Lightsail

Authors

Introduction

WireGuard is a modern, fast, and secure VPN protocol that offers excellent performance and ease of use.

This guide provides a complete, copy-paste ready solution for setting up WireGuard VPN on a AWS Lightsail instance running Ubuntu 24.04 LTS or later.

Prerequisites

Step 1: Create an AWS Lightsail Instance

  1. Log in to your AWS Console and navigate to Lightsail
  2. Click "Create instance"
  3. Choose your instance location
  4. Select "Linux/Unix" platform
  5. Under "Operating System (OS) only" select "Ubuntu 24.04 LTS" as the blueprint
  6. Select "Dual-stack" for network type for both IPv4 and IPv6
  7. Select the $5/month instance plan, at time of writing its (512 MB RAM, 2 vCPUs)
  8. Give your instance a name
  9. Click "Create instance"

Step 2: Configure Firewall

  1. Click on your instance
  2. Navigate to the "Networking" tab
  3. Add the following firewall rules for both IPv4 firewall and IPv6 firewall:
    • Custom UDP port 51820 (WireGuard)
    • TCP port 22 (SSH)
  4. Remove any default firewall rules for HTTP port 80.

Step 3: Connect to Your Instance

  1. Navigate to "Connect" tab of your instance.
  2. Click "Download default key", it will have a name in the form of LightsailDefaultKey-<region>.pem
  3. Change permission of downloaded key
chmod 600 LightsailDefaultKey-<region>.pem
  1. Get SSH username from the "User your SSH client" under "Connect" tab and ssh into instance:
ssh -i LightsailDefaultKey-<region>.pem ubuntu@your-instance-ip

Installation and Configuration

After SSH-ing into your AWS Lightsail instance, paste the following complete script. All keys and configurations will be automatically generated and properly set up. Note that the default interface is ens5 and not eth0.

#!/bin/bash

# Exit on any error
set -e

# Install required packages
echo "Installing required packages..."
sudo apt update
sudo apt install wireguard ufw qrencode -y

# Enable IP forwarding
echo "Configuring IP forwarding..."
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# Create WireGuard directory if it doesn't exist
sudo mkdir -p /etc/wireguard

# Generate server keys
echo "Generating server keys..."
wg genkey | sudo tee /etc/wireguard/server_private.key
sudo chmod 600 /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key

# Generate client keys
echo "Generating client keys..."
wg genkey | sudo tee /etc/wireguard/client_private.key
sudo cat /etc/wireguard/client_private.key | wg pubkey | sudo tee /etc/wireguard/client_public.key

# Get server public IP
SERVER_IP=$(curl http://checkip.amazonaws.com)
SERVER_PRIVATE_KEY=$(sudo cat /etc/wireguard/server_private.key)
CLIENT_PUBLIC_KEY=$(sudo cat /etc/wireguard/client_public.key)

# Create server configuration
echo "Creating server configuration..."
cat << EOF | sudo tee /etc/wireguard/wg0.conf
[Interface]
PrivateKey = ${SERVER_PRIVATE_KEY}
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = ufw route allow in on wg0 out on ens5
PostUp = iptables -t nat -I POSTROUTING -o ens5 -j MASQUERADE
PostUp = ip6tables -t nat -I POSTROUTING -o ens5 -j MASQUERADE
PostDown = ufw route delete allow in on wg0 out on ens5
PostDown = iptables -t nat -D POSTROUTING -o ens5 -j MASQUERADE
PostDown = ip6tables -t nat -D POSTROUTING -o ens5 -j MASQUERADE

[Peer]
PublicKey = ${CLIENT_PUBLIC_KEY}
AllowedIPs = 10.0.0.2/32
EOF

# Set correct permissions
sudo chmod 600 /etc/wireguard/wg0.conf

# Configure firewall
echo "Configuring firewall..."
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
echo "y" | sudo ufw enable

# Create client configuration
echo "Creating client configuration..."
SERVER_PUBLIC_KEY=$(sudo cat /etc/wireguard/server_public.key)
CLIENT_PRIVATE_KEY=$(sudo cat /etc/wireguard/client_private.key)

cat << EOF | sudo tee /etc/wireguard/client.conf
[Interface]
PrivateKey = ${CLIENT_PRIVATE_KEY}
Address = 10.0.0.2/32
DNS = 1.1.1.1, 1.0.0.1

[Peer]
PublicKey = ${SERVER_PUBLIC_KEY}
Endpoint = ${SERVER_IP}:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF

# Start WireGuard
echo "Starting WireGuard..."
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# Create directory for client configs
mkdir -p ~/wireguard-client-configs
sudo cp /etc/wireguard/client.conf ~/wireguard-client-configs/
chmod 700 ~/wireguard-client-configs

# Generate QR code
echo "Generating QR code..."
sudo cat /etc/wireguard/client.conf | qrencode -t ansiutf8  > ~/wireguard-client-configs/client-qr.txt

# Print status information
echo "
========================================
WireGuard Installation Complete!
========================================

Server Information:
- Public IP: ${SERVER_IP}
- Port: 51820
- Interface: wg0

Client configuration has been saved to:
~/wireguard-client-configs/client.conf

QR code for mobile clients has been saved to:
~/wireguard-client-configs/client-qr.txt

To check WireGuard status:
sudo wg show

To view the QR code for mobile clients:
cat ~/wireguard-client-configs/client-qr.txt
"

# Show WireGuard status
echo "Current WireGuard status:"
sudo wg show

Using the VPN

For Desktop Clients

  1. Install WireGuard client for your operating system:

  2. Copy the contents of ~/wireguard-client-configs/client.conf to your client machine

  3. Import the configuration into your WireGuard client

  4. Enable the VPN connection

For Mobile Clients

  1. Install WireGuard app:

  2. Scan the QR code displayed in ~/wireguard-client-configs/client-qr.txt

  3. Enable the VPN connection

Adding Additional Clients

To add more clients, run these commands on the server:

#!/bin/bash

# Generate keys for the new client
CLIENT_NUM=2  # Change this number for each new client
sudo wg genkey | sudo tee "/etc/wireguard/client${CLIENT_NUM}_private.key"
sudo cat "/etc/wireguard/client${CLIENT_NUM}_private.key" | wg pubkey | sudo tee "/etc/wireguard/client${CLIENT_NUM}_public.key"

# Get the keys and server info
NEW_CLIENT_PRIVATE_KEY=$(sudo cat "/etc/wireguard/client${CLIENT_NUM}_private.key")
NEW_CLIENT_PUBLIC_KEY=$(sudo cat "/etc/wireguard/client${CLIENT_NUM}_public.key")
SERVER_PUBLIC_KEY=$(sudo cat /etc/wireguard/server_public.key)
SERVER_IP=$(curl http://checkip.amazonaws.com)

# Add peer to server config
sudo tee -a /etc/wireguard/wg0.conf << EOF

[Peer]
PublicKey = ${NEW_CLIENT_PUBLIC_KEY}
AllowedIPs = 10.0.0.$((CLIENT_NUM + 1))/32
EOF

# Create client config
cat << EOF | sudo tee "/etc/wireguard/client${CLIENT_NUM}.conf"
[Interface]
PrivateKey = ${NEW_CLIENT_PRIVATE_KEY}
Address = 10.0.0.$((CLIENT_NUM + 1))/32
DNS = 1.1.1.1, 1.0.0.1

[Peer]
PublicKey = ${SERVER_PUBLIC_KEY}
Endpoint = ${SERVER_IP}:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF

# Generate QR code for the new client
sudo cat "/etc/wireguard/client${CLIENT_NUM}.conf" | qrencode -t ansiutf8  | sudo tee "/etc/wireguard/client${CLIENT_NUM}-qr.txt"

# Restart WireGuard to apply changes
sudo systemctl restart wg-quick@wg0

echo "New client configuration created:"
echo "Config file: /etc/wireguard/client${CLIENT_NUM}.conf"
echo "QR code: /etc/wireguard/client${CLIENT_NUM}-qr.txt"

Troubleshooting

If you encounter issues, check:

  1. WireGuard service status:
sudo systemctl status wg-quick@wg0
  1. Logs:
sudo journalctl -xeu wg-quick@wg0
  1. Interface status:
sudo wg show
ip addr show wg0
  1. Firewall status:
sudo ufw status
  1. IP forwarding status:
sysctl net.ipv4.ip_forward
sysctl net.ipv6.conf.all.forwarding

All commands in this guide are ready to use without any modifications. The script automatically generates all necessary keys and configurations, and provides clear output about where to find the client configuration files.