WireGuard Raspberry Pi 5: Complete Phone and Laptop Client Setup Guide

Wireguard vpn on raspberry pi 5 phone & laptop setup

WireGuard Raspberry Pi 5 gives you a self-hosted VPN server that connects your phone and laptop to your home network from anywhere. WireGuard is built into the Linux kernel, uses modern cryptography with minimal overhead, and runs fast enough on a Pi 5 to handle several simultaneous clients without measurable performance impact. This guide covers server installation and key generation, firewall and IP forwarding configuration, QR code client setup for Android and iOS, laptop client configuration for Windows, macOS, and Linux, split tunneling, LAN access, and troubleshooting.

Last tested: Raspberry Pi OS Bookworm Lite 64-bit | May 3, 2026 | Raspberry Pi 5 (4GB) | WireGuard 1.0.20210914 | WireGuard Android 1.0.20230706 | WireGuard Windows 0.5.3

Key Takeaways

  • WireGuard uses UDP port 51820 by default. Your router must forward UDP 51820 to the Pi’s static IP for external clients to connect. If your ISP uses CGNAT (common on mobile broadband), port forwarding will not work. Use Tailscale instead. See Tailscale Raspberry Pi.
  • Each client device needs its own unique key pair and its own IP address within the WireGuard subnet (10.0.0.x/32). Never reuse keys across devices. A shared key means if one device is compromised or lost, you must rotate keys for all devices sharing that key.
  • If your home IP is dynamic (changes when the router reboots), use DuckDNS or a similar DDNS service and put the domain name rather than the IP in the client Endpoint setting. A changing server IP breaks all client connections until the config is updated.

WireGuard Raspberry Pi 5: How It Differs from Site-to-Site VPN

This guide covers the road-warrior pattern: a single Pi server that mobile clients (phones, laptops) connect to from anywhere. Each client gets a private tunnel to the Pi and, through it, to your home network. This differs from a site-to-site configuration where two fixed networks tunnel to each other permanently. For the site-to-site setup, see WireGuard Raspberry Pi Site-to-Site VPN.

The road-warrior setup uses AllowedIPs = 0.0.0.0/0 for full tunnel (all traffic through the Pi) or a more specific subnet like 10.0.0.0/24, 192.168.1.0/24 for split tunnel. Full tunnel protects all traffic on untrusted networks. Split tunnel reduces bandwidth use and keeps non-sensitive traffic local.

OS and Hardware Preparation

Pi 5 with 4GB RAM handles WireGuard and several clients with negligible CPU load. WireGuard is a kernel module. Its overhead is minimal compared to OpenVPN or IPsec. Flash Raspberry Pi OS Bookworm Lite 64-bit using Raspberry Pi Imager. After first boot:

sudo apt update && sudo apt full-upgrade -y

Set a static IP so your router port forward always reaches the same address:

sudo nmcli connection modify "Wired connection 1"   ipv4.method manual   ipv4.addresses 192.168.1.200/24   ipv4.gateway 192.168.1.1   ipv4.dns 192.168.1.1
sudo nmcli connection up "Wired connection 1"

Confirm the network interface name your Pi uses. The PostUp iptables rules must reference this name:

ip link show
# Look for your primary interface: usually eth0 or end0 on Pi 5

Installing WireGuard and Generating Server Keys

sudo apt install wireguard qrencode -y

Generate the server key pair. The umask 077 ensures the private key file is created with restricted permissions:

umask 077
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key

Create /etc/wireguard/wg0.conf. Replace eth0 with your actual interface name from ip link show if it differs:

[Interface]
PrivateKey = $(sudo cat /etc/wireguard/server_private.key)
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

In practice, write the actual key value into the file rather than using command substitution in the config. Read the private key and paste it directly:

sudo cat /etc/wireguard/server_private.key
# Copy the output, then edit wg0.conf and replace the $(...)  with the actual key string
sudo chmod 600 /etc/wireguard/wg0.conf

IP Forwarding and Firewall

Enable IP forwarding persistently using a drop-in sysctl file rather than appending to the main sysctl.conf:

sudo tee /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
EOF
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf

Open UDP port 51820 and allow forwarding:

sudo apt install ufw -y
sudo ufw allow OpenSSH
sudo ufw allow 51820/udp
sudo ufw enable

Start WireGuard and enable it at boot:

sudo systemctl enable --now wg-quick@wg0
sudo wg

Expected result: sudo wg shows the wg0 interface with the server public key, listening port 51820, and an empty peer list. No peers have connected yet. That is expected at this stage.

WireGuard Raspberry Pi 5 VPN diagram showing Pi server phone client laptop client and home LAN access tunnel

Adding Client Peers

Each client device needs its own key pair. Generate keys for the first client:

umask 077
wg genkey | tee /tmp/client1_private | wg pubkey > /tmp/client1_public
cat /tmp/client1_private
cat /tmp/client1_public

Add the client as a peer in /etc/wireguard/wg0.conf. Append to the end of the file:

[Peer]
# Client 1: Phone
PublicKey = <paste client1_public here>
AllowedIPs = 10.0.0.2/32

Reload WireGuard to pick up the new peer without dropping existing connections:

sudo wg syncconf wg0 <(sudo wg-quick strip wg0)

Create the client configuration file. Replace YOUR_PUBLIC_IP with your home IP or DuckDNS domain:

cat > /tmp/client1.conf <<EOF
[Interface]
PrivateKey = $(cat /tmp/client1_private)
Address = 10.0.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = $(sudo cat /etc/wireguard/server_public.key)
Endpoint = YOUR_PUBLIC_IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF

Generate a QR code for mobile clients:

qrencode -t ansiutf8 < /tmp/client1.conf

Delete the temporary key files after use:

rm /tmp/client1_private /tmp/client1_public /tmp/client1.conf

Adding additional clients

Repeat the key generation and peer block for each device. Increment the IP address: client 2 gets 10.0.0.3/32, client 3 gets 10.0.0.4/32, and so on. Each client needs its own private key. Do not share keys between devices.

Configuring Mobile Clients

Install the official WireGuard app from Google Play (Android) or the App Store (iOS). Tap the plus button and select “Scan from QR code.” Point the camera at the QR code generated in the previous section. The configuration imports automatically.

Enable the tunnel and test the connection:

  • Visit https://ipinfo.io. Your public IP should match your home IP.
  • Visit https://dnsleaktest.com. DNS requests should resolve through your home network.
  • Try to reach a local device by LAN IP (e.g., 192.168.1.1). This requires split tunnel config covered below.

Expected result: sudo wg on the Pi shows a recent handshake timestamp for the connected peer and traffic counters incrementing.

On-demand activation

On Android, enable “Always-on VPN” and “Block connections without VPN” in Settings > Network > VPN to ensure the tunnel is always active on untrusted networks. On iOS, enable “On-Demand Activation” within the WireGuard app settings for the tunnel and configure it to activate on all networks or on cellular only.

Configuring Laptop Clients

Copy the client config file securely to the laptop. On Linux:

sudo apt install wireguard -y
sudo cp client2.conf /etc/wireguard/wg0.conf
sudo chmod 600 /etc/wireguard/wg0.conf
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

On Windows: download WireGuard from wireguard.com/install, click Add Tunnel > Import from file, and select the config file. On macOS: install from the Mac App Store and import the file.

Split tunnel for LAN access only

For a laptop that should access home LAN services but route internet traffic normally, change AllowedIPs in the client config:

[Peer]
PublicKey = <server-public-key>
Endpoint = YOUR_PUBLIC_IP:51820
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25

With this config, only traffic destined for the WireGuard subnet or the home LAN subnet goes through the tunnel. All other internet traffic routes normally without passing through the Pi.

On the server side, confirm the server peer entry for this client allows the LAN subnet:

[Peer]
# Client 2: Laptop (split tunnel)
PublicKey = <client2-public-key>
AllowedIPs = 10.0.0.3/32

Dynamic DNS for Changing Home IPs

If your ISP assigns a dynamic IP, the Endpoint address in client configs becomes stale when the IP changes. Use DuckDNS (free) to maintain a stable hostname:

# Install the DuckDNS update script
mkdir -p ~/duckdns
cat > ~/duckdns/duck.sh <<EOF
echo url="https://www.duckdns.org/update?domains=yourdomain&token=your-token&ip=" | curl -k -o ~/duckdns/duck.log -K -
EOF
chmod 700 ~/duckdns/duck.sh

# Update every 5 minutes via cron
(crontab -l 2>/dev/null; echo "*/5 * * * * ~/duckdns/duck.sh") | crontab -

Set the Endpoint in client configs to yourdomain.duckdns.org:51820 instead of a bare IP. WireGuard re-resolves the hostname on each handshake, so the connection recovers automatically when the home IP changes.

Maintenance

Checking connection status

# View all peers, handshake timestamps, and data transferred
sudo wg

# Check service status
sudo systemctl status wg-quick@wg0

# View WireGuard system logs
sudo journalctl -u wg-quick@wg0 -n 30

Revoking a client

Remove the peer block from /etc/wireguard/wg0.conf and reload:

sudo wg syncconf wg0 <(sudo wg-quick strip wg0)

The removed client can no longer connect. No restart required.

Backing up keys and config

sudo tar -czf ~/wireguard-backup-$(date +%Y%m%d).tar.gz /etc/wireguard/

Losing the server private key means every client config must be regenerated. Back it up to a secure location separate from the Pi.

Troubleshooting

No handshake from client

# Check WireGuard sees the interface
sudo wg show

# Confirm port 51820 UDP is open
sudo ss -ulnp | grep 51820

# Test from outside the network (mobile data, not home Wi-Fi)
# Check router port forward: UDP 51820 -> Pi static IP

The most common causes: the router port forward is missing or points to the wrong IP, the client Endpoint IP has changed (ISP reassigned), or the client public key in wg0.conf does not match the key in the client config. Mismatched keys produce no error message. WireGuard silently drops packets from unknown peers.

Client connects but cannot reach LAN

# Check IP forwarding is active
sysctl net.ipv4.ip_forward

# Check iptables NAT rule is present
sudo iptables -t nat -L POSTROUTING -n -v | grep MASQUERADE

# Confirm LAN subnet is in AllowedIPs on the client config

If IP forwarding is 0, the sysctl.d file did not apply. Run sudo sysctl -p /etc/sysctl.d/99-wireguard.conf to apply it immediately and confirm the value is 1.

Slow throughput or stalling connections

MTU mismatch is the most common cause of partial connectivity. Sites load slowly or connections stall after a few seconds. Add an MTU setting to both the server interface and the client interface:

[Interface]
# In wg0.conf on both server and client
MTU = 1380

1380 is a safe starting point for most mobile networks. If throughput improves, the problem was MTU. Experiment between 1280 and 1420 to find the optimal value for your network.

DNS leaks

# Test at dnsleaktest.com while connected to the VPN
# DNS requests should resolve through your home network or the DNS in the client config
# If leaking, ensure the client config has:
# DNS = 192.168.1.53  (your Pi-hole or AdGuard Home address)
# and AllowedIPs = 0.0.0.0/0 for full tunnel

FAQ

Can multiple devices connect simultaneously?

Yes. Each peer has its own key pair and its own IP address in the WireGuard subnet. All can be connected at the same time with independent tunnels. The Pi 5 handles 10 or more simultaneous WireGuard peers without measurable CPU impact. WireGuard’s kernel implementation is extremely efficient.

What if my ISP uses CGNAT?

With CGNAT, the router does not have a real public IP and port forwarding does not work. WireGuard clients cannot connect. Use Tailscale instead. It handles NAT traversal without requiring a public IP. See Tailscale Raspberry Pi.

How does this compare to Tailscale?

Both use WireGuard under the hood. Self-hosted WireGuard requires manual key management, port forwarding, and a public IP or DDNS. It has no external dependency after setup. Tailscale handles all of that automatically through a coordination server, works behind CGNAT, and is easier to set up. It does add a dependency on Tailscale servers. For a homelab where you control a static IP and want no external dependencies, self-hosted WireGuard is the better choice.

Can I use Pi-hole or AdGuard Home as the VPN DNS?

Yes. Set DNS = 192.168.1.53 (or whatever IP your Pi-hole or AdGuard Home listens on) in the client config instead of 1.1.1.1. All DNS queries from the VPN client route through your home ad blocker. This works with both full tunnel and split tunnel configurations as long as the DNS server IP is reachable through the tunnel. See Unbound Raspberry Pi and AdGuard Home Raspberry Pi.

Is WireGuard secure enough for sensitive traffic?

Yes. WireGuard uses ChaCha20 for symmetric encryption, Poly1305 for authentication, Curve25519 for key exchange, BLAKE2 for hashing, and SipHash for hashtable keys. The cryptographic surface is deliberately minimal, which makes it easier to audit than OpenVPN or IPsec. The protocol has been formally verified and is included in the Linux kernel as of version 5.6.

References


About the Author

Chuck Wilson has been programming and building with computers since the Tandy 1000 era. His professional background includes CAD drafting, manufacturing line programming, and custom computer design. He runs PidiyLab in retirement, documenting Raspberry Pi and homelab projects that he actually deploys and maintains on real hardware. Every article on this site reflects hands-on testing on specific hardware and OS versions, not theoretical walkthroughs.

Last tested hardware: Raspberry Pi 5 (4GB). Last tested OS: Raspberry Pi OS Bookworm Lite 64-bit. WireGuard 1.0.20210914, WireGuard Android app, WireGuard Windows 0.5.3.

Was this helpful?

Yes
No
Thanks for your feedback!