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:
- Edit
wg0.conf
:sudo nano /etc/wireguard/wg0.conf
- 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.