Tutorials Projects Hardware Topics About Newsletter

Self-Hosted WireGuard VPN on Raspberry Pi: Secure Remote Access

WireGuard is the fastest and most modern VPN protocol available. Running it on a Raspberry Pi gives you secure remote access to your home network without paying for a commercial VPN service. This guide covers the complete setup from installation to connecting your first client device.

Marcus Webb
Network Engineer - 9 years homelab experience - CompTIA Network+, Security+
Published: Jan 12, 2025

Why WireGuard over OpenVPN or commercial VPNs

WireGuard has a codebase roughly 100 times smaller than OpenVPN. Fewer lines of code means a smaller attack surface, faster security audits, and measurably lower overhead. Benchmarks consistently show WireGuard delivering 2 to 4 times the throughput of OpenVPN at lower latency.

Compared to commercial VPN services, running your own on a Raspberry Pi means your traffic goes directly to your home network rather than through a third-party server. You control the keys, the logs (or complete absence of them), and every endpoint.

Requirements

Before starting, make sure you have:

  • Raspberry Pi 3B+, 4, or 5 running Raspberry Pi OS 64-bit (Lite recommended)
  • Static local IP for your Pi - see our static IP guide first
  • Port forwarding access on your router - you will open UDP port 51820
  • A public hostname - if your ISP gives you a dynamic IP, set up DuckDNS first
[!]
CGNAT blocks incoming connections

Some ISPs, particularly mobile broadband providers, use carrier-grade NAT. If your router WAN IP starts with 100.64.x.x, you are behind CGNAT and cannot receive inbound connections. Use a Cloudflare Tunnel or a VPS relay as an alternative.

Step 1: Install WireGuard

WireGuard is included in the Linux kernel since version 5.6. On Raspberry Pi OS Bullseye or Bookworm, the kernel module is already present. Install the userspace tools:

sudo apt update
sudo apt install wireguard -y

Verify the module loads cleanly:

sudo modprobe wireguard
lsmod | grep wireguard

Step 2: Generate server keys

WireGuard uses public-key cryptography. Each endpoint needs its own key pair. Generate the server keys and set secure permissions:

wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
sudo chmod 600 /etc/wireguard/server_private.key

Note both values. You will need the server public key when configuring clients.

Step 3: Configure the WireGuard interface

Create the server configuration file:

sudo nano /etc/wireguard/wg0.conf

Add the following, replacing SERVER_PRIVATE_KEY with the content of server_private.key:

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY

PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

Save with Ctrl+X, Y, Enter. Lock down the config file permissions:

sudo chmod 600 /etc/wireguard/wg0.conf

Enable IP forwarding so VPN clients can reach your LAN devices:

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Step 4: Add client devices

For each device you want to connect, generate a client key pair on the Pi:

wg genkey | tee client1_private.key | wg pubkey > client1_public.key

Add the client as a peer in wg0.conf:

[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32

Create a client configuration to import into the WireGuard app:

[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY
Address = 10.8.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = your-ddns-hostname.duckdns.org:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Use AllowedIPs = 192.168.1.0/24 instead of 0.0.0.0/0 for split tunneling, where only home network traffic routes through the VPN.

Step 5: Start WireGuard and enable on boot

Start the interface and enable automatic startup:

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

The wg show output should display your server public key and listening port.

Step 6: Port forwarding on your router

Log into your router admin panel and create a UDP port forwarding rule pointing external UDP port 51820 to your Pi's static LAN IP on port 51820. The exact menu location varies by router model but is usually found under Advanced, NAT, or Firewall settings.

Testing the connection

Install the WireGuard app on your phone from the App Store or Google Play. Import the client configuration file or scan a QR code generated with:

qrencode -t ansiutf8 < client1.conf

Turn off Wi-Fi on your phone so it uses mobile data, then toggle the VPN tunnel on. Try accessing a device on your home LAN by its local IP address. On the Pi, run sudo wg show to confirm the latest handshake.

Troubleshooting common issues

No handshake after connecting: Verify UDP port 51820 is correctly forwarded in your router. Test with an external port checker tool.

Connected but cannot reach LAN devices: Confirm IP forwarding is active: cat /proc/sys/net/ipv4/ip_forward should return 1. Verify the PostUp iptables rules are present in wg0.conf.

DNS not resolving: Set the DNS in your client config to your Pi's LAN IP if you run Pi-hole, or use 1.1.1.1 as a fallback.

Marcus Webb
Homelab Engineer and RPiServer.com Co-Founder

Marcus has run WireGuard on Raspberry Pi since it was merged into the Linux kernel in 2020. He tests every network guide on a Pi 4 and Pi 5 before publishing.

Tags