Setup WireGuard VPN on Vultr

Authors

WireGuard is a modern, fast, and secure VPN protocol that offers excellent performance and ease of use. This guide will walk you through setting up a WireGuard VPN server on a Vultr with both IPv4 and IPv6 support.

Prerequisites

  • A Debian 12 (or newer) Cloud Compute - Shared CPU instance in the desired data center region.
  • Before deploying new instance:
    • Disable Auto Backups
    • Select IPv6
    • Add SSH key (usually contents of your ~/.ssh/id_rsa.pub)

Step 1: Initial Server Setup

Once created, SSH into your server:

ssh root@your_server_ip

Update package sources list with the latest versions of the packages:

apt update

Step 2: Install WireGuard

Install WireGuard and required tools:

apt install wireguard ufw -y

Enable IP forwarding for both IPv4 and IPv6 by editing /etc/sysctl.conf:

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -p

Step 3: Generate Server Keys

Generate the server's private and public keys:

cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey

Step 4: Configure WireGuard Server

Create and edit the WireGuard configuration file:

cat > /etc/wireguard/wg0.conf <<EOF
[Interface]
PrivateKey = $(cat privatekey)
Address = 10.0.0.1/24, fd86:ea04:1115::1/64
ListenPort = 51820
SaveConfig = true

PostUp = ufw route allow in on wg0 out on enp1s0
PostDown = ufw route delete allow in on wg0 out on enp1s0

# IPv4
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -I POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE

# IPv6
PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT
PostUp = ip6tables -t nat -I POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT
PostDown = ip6tables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE


# (Client peers will be added in following sections, here for demonstration)
# Client 1
#[Peer]
#PublicKey = <client1_public_key>
#AllowedIPs = 10.0.0.2/32, fd86:ea04:1115::2/128

# Client 2
#[Peer]
#PublicKey = <client2_public_key>
#AllowedIPs = 10.0.0.3/32, fd86:ea04:1115::3/128
EOF

Note that the default interface on Vultr is enp1s0 and not eth0.

Step 5: Configure Firewall

Set up UFW firewall rules for both IPv4 and IPv6:

ufw allow 51820/udp
ufw allow OpenSSH
ufw enable

Confirm when prompted for Command may disrupt existing ssh connections. Proceed with operation (y|n)?

Step 6: Start WireGuard Service

Enable and start the WireGuard service:

systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

Confirm wg0 interface with wg show command.

Step 7: Generate Client Configurations

For each client, generate a new key pair:

mkdir -p /etc/wireguard/clients
cd /etc/wireguard/clients
wg genkey | tee client1_private.key | wg pubkey > client1_public.key

Create a client configuration file:

# Get server IPv6 address
SERVER_IPV6=$(ip -6 addr show dev enp1s0 | grep -oP '(?<=inet6 )([0-9a-f:]+)' | head -1)

cat > client1.conf << EOF
[Interface]
PrivateKey = $(cat client1_private.key)
Address = 10.0.0.2/32, fd86:ea04:1115::2/128
DNS = 1.1.1.1, 2606:4700:4700::1111

[Peer]
PublicKey = $(cat ../publickey)
Endpoint = [$SERVER_IPV6]:51820
# Or use IPv4: Endpoint = your_server_ipv4:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF

Step 8: Add Client to Server

Add the client's public key to the server:

wg set wg0 peer $(cat client1_public.key) allowed-ips 10.0.0.2/32,fd86:ea04:1115::2/128

Confirm that peer was successfully added by running wg show command.

Complete Setup Script

Here's the complete script for setting up WireGuard with IPv6 support:

#!/bin/bash

# Update package sources list with the latest versions of the packages:
apt update

# Install WireGuard
apt install wireguard ufw -y

# Enable IP forwarding for IPv4 and IPv6
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -p

# Generate server keys
cd /etc/wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey

# Create server configuration
cat > /etc/wireguard/wg0.conf << EOF
[Interface]
PrivateKey = $(cat privatekey)
Address = 10.0.0.1/24, fd86:ea04:1115::1/64
ListenPort = 51820
SaveConfig = true

PostUp = ufw route allow in on wg0 out on enp1s0
PostDown = ufw route delete allow in on wg0 out on enp1s0

# IPv4
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -I POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE

# IPv6
PostUp = ip6tables -A FORWARD -i wg0 -j ACCEPT
PostUp = ip6tables -t nat -I POSTROUTING -o enp1s0 -j MASQUERADE
PostDown = ip6tables -D FORWARD -i wg0 -j ACCEPT
PostDown = ip6tables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE
EOF

# Configure firewall
ufw allow 51820/udp
ufw allow OpenSSH
ufw enable

# Start WireGuard
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

# Create client directory
mkdir -p /etc/wireguard/clients

# Generate client keys
cd /etc/wireguard/clients
wg genkey | tee client1_private.key | wg pubkey > client1_public.key

# Get server IPv6 address
SERVER_IPV6=$(ip -6 addr show dev enp1s0 | grep -oP '(?<=inet6 )([0-9a-f:]+)' | head -1)

# Create client configuration
cat > client1.conf << EOF
[Interface]
PrivateKey = $(cat client1_private.key)
Address = 10.0.0.2/32, fd86:ea04:1115::2/128
DNS = 1.1.1.1, 2606:4700:4700::1111

[Peer]
PublicKey = $(cat ../publickey)
Endpoint = [$SERVER_IPV6]:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF

# Add client to server configuration
wg set wg0 peer $(cat client1_public.key) allowed-ips 10.0.0.2/32,fd86:ea04:1115::2/128

Connect Client Device

Download the client configuration file client1.conf securely to your device to connect using the official WireGuard client.

On a mobile device, you can scan the QR code for the client configuration:

apt install qrencode -y
qrencode -t ansiutf8 < /etc/wireguard/clients/client1.conf