🔒 WireGuard VPN — Raspberry Pi (Server)
This document explains how to install and configure WireGuard on a Raspberry Pi to run a simple VPN server. It covers a recommended (apt-based) install, key generation, a sample server and client configuration, NAT/firewall setup, enabling the service, and troubleshooting tips. All commands assume a Debian/Raspberry Pi OS environment and use sudo where required.
✅ Prerequisites
- Raspberry Pi (preferably 64-bit OS for best compatibility) with network access
- SSH or local terminal access with a sudo user
- A public IP on the Pi or port forwarded on your router (UDP port 51820 by default)
- Basic Linux networking knowledge
Recommended: use system packages (simple & maintained)
Modern Raspberry Pi OS includes WireGuard packages. Prefer the package install unless you need a custom build.
sudo apt update
sudo apt install -y wireguard iproute2
# Optional helpers:
sudo apt install -y qrencode openresolv # qrencode for scanning client config; openresolv for resolvconf support
If a kernel module is missing, install kernel headers first (only rarely needed):
sudo apt install -y raspberrypi-kernel-headers build-essential libelf-dev
# Then (if you must) build modules — generally not required on recent OS versions.
1) Create keys and directories
Generate server keypair and a directory to store configs:
sudo -i
mkdir -p /etc/wireguard
chmod 700 /etc/wireguard
cd /etc/wireguard
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key
wg genkey | tee server_psk.key | wg pubkey > server_psk_pub.key # optional preshared key step
exit
Keep the private key secret. Example to view keys (as root only):
sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.key
2) Example wg0 (server) configuration
Create /etc/wireguard/wg0.conf (adjust values for your network):
[Interface]
# Server private key (from server_private.key)
PrivateKey = <SERVER_PRIVATE_KEY>
Address = 10.0.0.1/24 # VPN subnet
ListenPort = 51820 # UDP port on host
SaveConfig = true
# Optional: DNS for clients
# PostUp/Down manage NAT and firewall (see alternatives below)
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Example peer (replace with real client public key and allowed IP)
[Peer]
# Client 1
PublicKey = <CLIENT_PUBLIC_KEY>
PresharedKey = <PRESHARED_KEY> # optional
AllowedIPs = 10.0.0.2/32 # VPN IP assigned to this client
Notes:
- Replace
<SERVER_PRIVATE_KEY>and<CLIENT_PUBLIC_KEY>with actual keys. eth0is the Pi's uplink interface — change if different (e.g.eth0,enxb...,wlan0).AllowedIPs = 0.0.0.0/0on the client peer entry will route all client traffic through the VPN (full tunnel).
3) Generate client keys and config
On your client machine or on the Pi (then securely copy), create keys:
wg genkey | tee client_private.key | wg pubkey > client_public.key
wg genkey | tee client_psk.key | wg pubkey > client_psk_pub.key # optional preshared
Example client config (for Linux/Windows/macOS/iOS/Android):
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.0.0.2/32
DNS = 1.1.1.1, 8.8.8.8 # optional: DNS to use while connected
[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
PresharedKey = <PRESHARED_KEY> # optional
Endpoint = your.public.ip.or.ddns:51820
AllowedIPs = 0.0.0.0/0 # route all traffic via VPN (or restrict to LAN ranges)
PersistentKeepalive = 25
Generate a QR code for mobile clients:
sudo apt install -y qrencode
qrencode -t ansiutf8 < /etc/wireguard/client.conf
# or
qrencode -o client.png -r /etc/wireguard/client.conf
4) Enable IP forwarding
Persist forwarding in sysctl:
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
5) NAT / Firewall examples
A) iptables via PostUp/PostDown in wg0.conf (quick):
- Already shown in the wg0.conf snippet using
PostUp/PostDown.
B) firewalld example:
sudo apt install -y firewalld
sudo systemctl enable --now firewalld
# Allow WireGuard port
sudo firewall-cmd --permanent --add-port=51820/udp
# Enable masquerade (NAT)
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload
C) nftables example (modern Linux):
# Example NAT rule (adjust interface names)
sudo nft add table ip nat
sudo nft 'add chain ip nat POSTROUTING { type nat hook postrouting priority 100 ; }'
sudo nft add rule ip nat POSTROUTING oifname "eth0" snat to :0x0/0x0 masquerade
# Save rules with your distro's nftables persistence method
Pick one method — do not mix conflicting NAT rules.
6) Start and enable service
Bring up the interface and enable at boot:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
# or bring up immediately
sudo wg-quick up wg0
Check status and peers:
sudo wg show
ip -4 addr show dev wg0
sudo systemctl status wg-quick@wg0 --no-pager
7) Verify connectivity
- From server: check wg, IPs and netfilter:
sudo wg
ip route
sudo iptables -t nat -L -n -v # if using iptables
- From client: check assigned VPN IP and try ping:
ip a # client should have 10.10.0.2
ping 10.10.0.1 # ping server VPN IP
curl ifconfig.me # verify public IP if routing all traffic via VPN
8) Client routing notes
- To access your home LAN (e.g. 192.168.1.0/24) from the client, add AllowedIPs for that range on the server peer and on the client set AllowedIPs to include that subnet (or use 0.0.0.0/0 for full tunnel).
- Example peer AllowedIPs for split tunnel:
- Server peer: AllowedIPs = 10.10.0.2/32
- Client allowed: AllowedIPs = 10.10.0.0/24, 192.168.1.0/24
9) Security & best practices
- Keep server private key secret; regenerate if compromised.
- Use a strong preshared key (PSK) for additional security.
- Use a non-default UDP port if desired and restrict access via firewall.
- Use DNS and endpoint protection for client privacy.
- Regularly update the system and WireGuard packages.
10) Troubleshooting
- Interface won't come up:
- Inspect
sudo systemctl status wg-quick@wg0andsudo journalctl -u wg-quick@wg0. - Check keys and file permissions (wg files must be readable by root only).
- Inspect
- No traffic through VPN:
- Confirm IP forwarding and NAT rules.
- Confirm firewall allows UDP 51820.
- Verify AllowedIPs are configured correctly on both sides.
- Peer shows handshake but no internet:
- Check PostUp/NAT and DNS settings for client.
Commands that help:
sudo wg show
sudo journalctl -u wg-quick@wg0 -f
ip route show
sudo iptables -S
sudo nft list ruleset
11) Example quick commands summary
# Install
sudo apt update
sudo apt install -y wireguard qrencode openresolv
# Create keys
mkdir -p /etc/wireguard && chmod 700 /etc/wireguard
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
# Configure wg0.conf and enable
sudo nano /etc/wireguard/wg0.conf
sudo systemctl enable --now wg-quick@wg0
sudo sysctl --system