
Setting up a WireGuard VPN on a Raspberry Pi is one of the best home networking projects you can do — WireGuard is faster, simpler, and more auditable than OpenVPN, and it runs natively in the Linux kernel. This guide walks through the complete WireGuard VPN Raspberry Pi configuration: server setup, key generation, client config for iOS, Android, and macOS, and integration with Pi-hole for network-wide ad blocking over VPN.
What you need
- A Raspberry Pi (3B+, 4B, or 5 recommended)
- Raspberry Pi OS Lite (64-bit preferred)
- A static IP or DDNS hostname pointing to your home network
- Port forwarding: UDP 51820 open on your router, forwarded to the Pi’s local IP
Install WireGuard
On Raspberry Pi OS (Bullseye or later), WireGuard is in the standard repos:
sudo apt update && sudo apt install -y wireguard
Generate server keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
chmod 600 /etc/wireguard/server_private.key
Note the values — you’ll need them in the config:
cat /etc/wireguard/server_private.key
cat /etc/wireguard/server_public.key
WireGuard VPN Raspberry Pi server configuration
Find your network interface name first:
ip -o -4 route show to default | awk '{print $5}'
# Typically: eth0 or wlan0
Create /etc/wireguard/wg0.conf:
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = YOUR_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
Enable IP forwarding
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Add a client peer
wg genkey | tee /etc/wireguard/client1_private.key | wg pubkey > /etc/wireguard/client1_public.key
Add to wg0.conf:
[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32
Client config file:
[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY
Address = 10.8.0.2/24
DNS = 10.8.0.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = your-ddns-or-public-ip:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Start the WireGuard server
sudo systemctl enable --now wg-quick@wg0
sudo wg show
Import the client config
iOS / Android: Generate a QR code:
sudo apt install -y qrencode
qrencode -t ansiutf8 < /etc/wireguard/client1.conf
macOS: Install the WireGuard app from the App Store and import the .conf file.
Combine WireGuard with Pi-hole
If you're running Pi-hole on the same device, set DNS = 10.8.0.1 in the client config. All DNS queries from your phone will go through Pi-hole when the VPN is active — ad blocking works on any network, not just at home.
Troubleshooting
- Handshake not completing — check port forwarding and that UDP 51820 is open on the server firewall
- Connected but no internet — check IP forwarding is enabled and the iptables MASQUERADE rule is applied
- DNS not resolving — ensure Pi-hole listens on the
wg0interface - Traffic drops — add
PersistentKeepalive = 25to keep the connection alive through NAT
Related posts
Looking to extend your Raspberry Pi home server? Check out Docker on a Raspberry Pi to run self-hosted services, or Pi-hole with VPN for network-wide ad blocking. You can also set up passwordless SSH to manage your Pi securely without typing passwords.