Why WireGuard and Why a Raspberry Pi
WireGuard is a modern VPN protocol that strips away the complexity that made older solutions like OpenVPN and IPsec so tedious to configure. Its codebase is a fraction of the size, it uses state-of-the-art cryptography by default, and on most hardware it performs noticeably faster than the alternatives. For anyone who wants a private tunnel for remote access to a home network – or just a way to route traffic through a trusted server while traveling – WireGuard is the right starting point.
A Raspberry Pi makes an almost ideal host for a personal VPN server. It draws very little power running continuously, costs under $50 for a capable board, and runs a full Linux environment that WireGuard supports natively. This guide walks through the entire setup from a fresh Raspberry Pi OS install to a working VPN tunnel you can connect to from any device.

What You Need Before Starting
The requirements are minimal but non-negotiable. You need a Raspberry Pi – any model with a network port works, though a Pi 4 handles multiple simultaneous clients without breaking a sweat. Flash Raspberry Pi OS Lite (the headless version is fine) to a microSD card using the Raspberry Pi Imager, enable SSH in the imager’s settings before writing, and boot the Pi connected to your router via Ethernet. Set a static local IP address on the Pi through your router’s DHCP reservation table – this keeps the local network address predictable. You also need a way to expose the Pi to the internet, which means either a static public IP from your ISP or a dynamic DNS service like DuckDNS that maps a hostname to your changing IP.
On your router, open UDP port 51820 and forward it to the Pi’s static local IP. WireGuard uses UDP exclusively, so TCP rules will not help here. With that done, SSH into the Pi and run sudo apt update && sudo apt upgrade -y to make sure the system is current before touching anything else.
Installing WireGuard and Generating Keys
WireGuard is available directly from the Raspberry Pi OS repositories. Install it with a single command: sudo apt install wireguard -y. Once that completes, move into the WireGuard configuration directory with cd /etc/wireguard and set strict permissions so private keys are not readable by other users: umask 077.
Generate the server’s private and public key pair with wg genkey | tee server_private.key | wg pubkey > server_public.key. Read and note both values – you will need the private key in the server config and the public key in every client config. Repeat this key generation process for each client device you plan to connect. Keep the private keys private and never share them across devices or configs.

Configuring the Server
Create the server configuration file at /etc/wireguard/wg0.conf. The file follows a straightforward INI-style format. The [Interface] block defines the server itself: set Address to a private subnet address like 10.0.0.1/24, set ListenPort to 51820, and paste the server’s private key next to PrivateKey. If you want VPN clients to route all their internet traffic through the Pi rather than only access the local network, add two PostUp and PreDown rules that enable NAT masquerading through iptables.
The PostUp line should read: PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE. The PreDown line mirrors it with -D flags to clean up when the interface goes down. You also need to enable IP forwarding on the Pi so it can route packets between the VPN interface and the ethernet interface. Add or uncomment net.ipv4.ip_forward=1 in /etc/sysctl.conf, then apply it immediately with sudo sysctl -p. Without this step, client traffic will reach the Pi but go no further.
For each client device, add a [Peer] block to the server config. Set PublicKey to that client’s public key, and set AllowedIPs to the specific IP address you want to assign that client within the VPN subnet – for example, 10.0.0.2/32 for the first client. This tells WireGuard which client IP address maps to which public key. You can add as many peer blocks as you need, each with a unique VPN IP address. Save the file when done.
Enable and start the WireGuard interface with sudo systemctl enable wg-quick@wg0 && sudo systemctl start wg-quick@wg0. Check that it came up without errors using sudo wg show – you should see the interface listed with its public key and the listening port. If the interface fails to start, the most common culprits are a typo in the config file or a missing kernel module, which you can load manually with sudo modprobe wireguard.
Connecting a Client Device
WireGuard has official apps for Windows, macOS, iOS, and Android, all of which import configs either as files or QR codes. The client config file follows the same format: a [Interface] block with the client’s private key and its assigned VPN IP (10.0.0.2/24), and a [Peer] block pointing to the server with the server’s public key, the server’s public IP or DNS hostname plus port as the Endpoint, and an AllowedIPs value of 0.0.0.0/0 if you want all traffic routed through the VPN, or just the VPN subnet if you only want access to home network resources.
Generate a QR code from the client config file using the qrencode package (sudo apt install qrencode -y) and the command qrencode -t ansiutf8 . Scan it directly from the WireGuard mobile app to import the config without typing anything. On desktop, copy the conf file over and import it through the app’s interface. Once connected, run a quick check with sudo wg show on the Pi – you should see a recent handshake timestamp for the peer, which confirms a live tunnel. If you are already running other self-hosted services on the Pi, like Homebridge for HomeKit integration, the VPN gives you secure remote access to those services without exposing additional ports to the internet.

One thing worth watching after the setup is DNS leaks. Even with all traffic routed through the tunnel, your device may still send DNS queries outside of it depending on how the client OS handles DNS. Setting a DNS line in the client’s [Interface] block – pointing to something like 1.1.1.1 or a Pi-hole on the same local network – forces DNS through the tunnel and closes that gap. Whether that matters depends entirely on your threat model, but leaving it unaddressed while assuming full privacy coverage is a false sense of security worth avoiding.
Frequently Asked Questions
Which Raspberry Pi model works best for a WireGuard VPN server?
Any model works, but the Raspberry Pi 4 handles multiple simultaneous clients most comfortably without performance issues.
Do I need a static public IP address to run WireGuard on a Raspberry Pi?
Not necessarily. A dynamic DNS service like DuckDNS can map a changing public IP to a consistent hostname your clients can connect to.
What port does WireGuard use and do I need to open it on my router?
WireGuard uses UDP port 51820 by default. You need to forward that port on your router to the Pi’s local IP address for external connections to reach the server.





