Introduction

WireGuard is a modern VPN that enables secure remote access to your VPS or Raspberry Pi while minimizing public exposure. With only port 51820 exposed, WireGuard provides:

  • Secure access to Docker containers and internal services
  • Connection to databases, monitoring tools, and network services
  • Remote management of your infrastructure through an encrypted tunnel

WireGuard is ideal for both VPS-hosted services and Raspberry Pi home/office servers, keeping your servers secure and accessible globally.

Prerequisites

VPS

Ensure your VPS has a public IP address and that WireGuard port 51820 is opened in the firewall. This allows access to VPS services without exposing other ports to the public.

Raspberry Pi

Ensure your Raspberry Pi is connected to a home or office network, for example with a local network of 192.168.0.0/24 and Raspberry Pi assigned an IP of 192.168.0.100. Enable port forwarding for 51820 on your router. Your internet connection should have a static IP address, or you can use Duck DNS to assign a domain that automatically updates periodically.


Configuring WireGuard on Linux Server Machine

1. Install WireGuard

sudo apt install wireguard -y

2. Set Up the Working Directory

Organize your WireGuard files in a dedicated directory.

cd ~
mkdir wg
cd wg

3. Generate Server and Client Keys

Generate unique keys for the server and two clients (e.g., laptop and phone).

# Server keys
sudo bash -c 'wg genkey | tee /etc/wireguard/server_private.key | (read private_key && echo "Server Private Key: $private_key" && echo "$private_key" | wg pubkey | tee /etc/wireguard/server_public.key)'

# Client 1 keys
sudo bash -c 'wg genkey | tee client_1_private.key | (read private_key && echo "Client #1 Private Key: $private_key" && echo "$private_key" | wg pubkey | tee client_1_public.key)'

# Client 2 keys
sudo bash -c 'wg genkey | tee client_2_private.key | (read private_key && echo "Client #2 Private Key: $private_key" && echo "$private_key" | wg pubkey | tee client_2_public.key)'

Set appropriate permissions to keep keys secure

sudo chmod 600 /etc/wireguard/server_private.key

4. Configure the Server (wg0.conf)

Configure the server to assign unique IPs to each client for secure connections.

Note: The internal network for WireGuard will use 10.9.0.0/24.

sudo bash -c '
SERVER_PRIVATE_KEY=$(cat /etc/wireguard/server_private.key) &&
CLIENT_1_PUBLIC_KEY=$(cat client_1_public.key) &&
CLIENT_2_PUBLIC_KEY=$(cat client_2_public.key) &&
CLIENT_1_IP="10.9.0.2/32" &&
CLIENT_2_IP="10.9.0.3/32" &&

echo -e "[Interface]
PrivateKey = $SERVER_PRIVATE_KEY
Address = 10.9.0.1/24
ListenPort = 51820

[Peer]
PublicKey = $CLIENT_1_PUBLIC_KEY
AllowedIPs = $CLIENT_1_IP

[Peer]
PublicKey = $CLIENT_2_PUBLIC_KEY
AllowedIPs = $CLIENT_2_IP" > /etc/wireguard/wg0.conf
'

5. Configure Client Files

Each client requires a configuration file to connect to the server. Replace {SERVER_IP} with the actual VPS server IP address (e.g., 203.0.113.45) or a Duck DNS domain (e.g., your-domain.duckdns.org).

Client 1 (client_1.conf)

sudo bash -c '
CLIENT_1_PRIVATE_KEY=$(cat client_1_private.key) &&
SERVER_PUBLIC_KEY=$(cat /etc/wireguard/server_public.key) &&
SERVER_IP="{SERVER_IP}" &&

echo -e "[Interface]
PrivateKey = $CLIENT_1_PRIVATE_KEY
Address = 10.9.0.2/24

[Peer]
PublicKey = $SERVER_PUBLIC_KEY
Endpoint = $SERVER_IP:51820
AllowedIPs = 10.9.0.0/24" > client_1.conf
'

Client 2 (client_2.conf)

sudo bash -c '
CLIENT_2_PRIVATE_KEY=$(cat client_2_private.key) &&
SERVER_PUBLIC_KEY=$(cat /etc/wireguard/server_public.key) &&
SERVER_IP="{SERVER_IP}" &&

echo -e "[Interface]
PrivateKey = $CLIENT_2_PRIVATE_KEY
Address = 10.9.0.3/24

[Peer]
PublicKey = $SERVER_PUBLIC_KEY
Endpoint = $SERVER_IP:51820
AllowedIPs = 10.9.0.0/24" > client_2.conf
'

To retrieve the client configuration files from the server, use rsync to securely copy them to your local machine:

rsync -avz {USERNAME}@{SERVER_IP}:~/wg/client_1.conf ./client_1.conf
rsync -avz {USERNAME}@{SERVER_IP}:~/wg/client_2.conf ./client_2.conf

6. Accessing the Local Network via WireGuard (Optional)

To allow VPN clients to access devices on the local network (e.g., 192.168.0.0/24), add the following PostUp and PreDown rules to the WireGuard server configuration (wg0.conf), set up the client to route local network traffic through WireGuard, and specify DNS settings if needed.

Server Configuration (wg0.conf)

Add these lines under [Interface] in the wg0.conf file on the Raspberry Pi:

PostUp = iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
PostUp = iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -s 10.9.0.0/24 -j MASQUERADE
PreDown = iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT
PreDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPT
PreDown = iptables -t nat -D POSTROUTING -o eth0 -s 10.9.0.0/24 -j MASQUERADE
  • These rules enable forwarding between the VPN (wg0) and local network (eth0) and apply NAT to allow devices on the local network to respond to VPN clients.

Client Configuration

In the client configuration file (e.g., client_1.conf), update the [Peer] section to route traffic for both the VPN network and local network through WireGuard.

AllowedIPs = 10.9.0.0/24, 192.168.0.0/24
  • Adding 192.168.0.0/24 allows the client to access the local network via the VPN.

If you want the Raspberry Pi (WireGuard server) to handle DNS for VPN clients, add the following line in the [Interface] section of the client configuration:

DNS = 192.168.0.100

This setting uses the Raspberry Pi’s IP for DNS resolution when connected.

7. Enable and Start the WireGuard Service

Enable and start the WireGuard service to activate it at boot and manage secure connections.

sudo systemctl enable [email protected]
sudo systemctl start [email protected]
sudo systemctl status [email protected]

8. Verify WireGuard Status

Check the WireGuard interface to confirm your VPN connections are functioning as expected.

sudo wg

9. Update WireGuard Configuration (Optional)

To add new peers or modify existing configurations:

  1. Edit wg0.conf:
    sudo nano /etc/wireguard/wg0.conf
    
  2. Apply the changes:
    sudo wg syncconf wg0 /etc/wireguard/wg0.conf
    

Note: If SaveConfig = true, wg syncconf will apply changes from wg0.conf but won’t save runtime changes. Ensure wg0.conf has all intended settings to avoid overwriting.