Skip to main content

🔒 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

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.
  • eth0 is the Pi's uplink interface — change if different (e.g. eth0, enxb..., wlan0).
  • AllowedIPs = 0.0.0.0/0 on 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@wg0 and sudo journalctl -u wg-quick@wg0.
    • Check keys and file permissions (wg files must be readable by root only).
  • 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