Self-Hosted WireGuard Setup Guide for Home Labs and VPSs
This article contains affiliate links. If you sign up for a service through one of these links, we may receive a commission at no additional cost to you. We only recommend tools we would use ourselves — see our editorial policy.
WireGuard has become the default recommendation for many self-hosters who want a modern VPN without the weight and complexity that often come with older stacks. It is fast, relatively easy to audit conceptually, and practical for the two most common use cases in small environments: secure remote access into a home lab and encrypted links between servers. If you are weighing it against a managed mesh option, our Tailscale vs WireGuard comparison covers that trade-off in detail; this guide is for running plain WireGuard yourself.
The attraction is simple. WireGuard has a smaller configuration surface than many legacy VPN systems, uses well-regarded cryptographic primitives, and is built around a straightforward key-based model. That does not make it magical, but it does make it easier to operate well.
Plan before you install
A sane WireGuard deployment starts before you install anything. Decide what the tunnel is for.
- Remote access to your home network from a laptop or phone
- Site-to-site connectivity between two locations
- A private management path to cloud servers
- A full-tunnel privacy route for selected devices
That purpose determines routing, DNS, firewall rules, and whether you need split tunneling or full tunneling. A lot of VPN frustration comes from skipping this design step and trying random settings until something pings.
For a typical self-hosted setup, you need:
- one server with a stable public endpoint or reachable port forwarding
- WireGuard installed on the server and each client
- a private subnet for the tunnel, such as
10.10.0.0/24 - firewall rules allowing UDP on the chosen WireGuard port
- IP forwarding enabled on the server if clients need access beyond the VPN host itself
If you do not already have a public server, almost any small VPS will do — WireGuard's resource needs are tiny. Hetzneroffers small VPS plans to compare against your VPN throughput and bandwidth requirements, and Vultr is worth a look if you want a location physically close to you, which keeps latency down. If you plan to run more than a VPN on the box, our guide to choosing a VPS for a self-hosted stack walks through sizing in more depth.
The core model is refreshingly direct. Each peer gets a private key and a public key. The server configuration defines its own address and lists peers. Each client does the same. Peers also define AllowedIPs, which is one of the most important and most misunderstood settings. It acts both as a routing instruction and as a peer identity constraint. If you get AllowedIPs wrong, you may accidentally break routing or create overlapping paths.
For remote access, a practical pattern is to give the server 10.10.0.1/24 and assign each client a fixed address like 10.10.0.2/32. On the client, AllowedIPs might be just your home LAN and VPN subnet if you want split tunneling, or 0.0.0.0/0 for IPv4 full-tunnel routing. Do not add ::/0 unless you have also configured and tested IPv6 forwarding, addresses, and firewall rules.
Minimal working config
Here is the shortest path to a working remote-access tunnel on Ubuntu or Debian. Install WireGuard on the server and generate a key pair for each side:
sudo apt update && sudo apt install wireguard
# On the server (as root, keys are sensitive):
cd /etc/wireguard
umask 077
wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee client.key | wg pubkey > client.pub
Generating the client's keys on the server is fine for a first test; for real deployments, generate them on the client device so the private key never travels.
Create /etc/wireguard/wg0.conf on the server:
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <contents of server.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
[Peer]
PublicKey = <contents of client.pub>
AllowedIPs = 10.10.0.2/32
The PostUp/PostDown lines only matter if clients should reach networks beyond the VPN host itself; adjust eth0 to your server's actual outbound interface (check with ip route). Then the client config, on the laptop or phone:
[Interface]
Address = 10.10.0.2/32
PrivateKey = <contents of client.key>
[Peer]
PublicKey = <contents of server.pub>
Endpoint = your.server.public.ip:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25
That AllowedIPs gives you split tunneling: only VPN-subnet traffic uses the tunnel. Add your home LAN subnet (for example 192.168.1.0/24) to reach devices behind the server, or use 0.0.0.0/0 for full-tunnel routing. PersistentKeepalive = 25 keeps the connection alive through NAT, which nearly every home or mobile client sits behind.
Finally, enable forwarding, open the port, and bring the interface up:
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sudo ufw allow 51820/udp
sudo systemctl enable --now wg-quick@wg0
sudo wg show
If UFW or another firewall enforces forwarding policies, configure that firewall to allow the intended VPN-to-uplink traffic and established return traffic as well; allowing UDP 51820 only permits handshakes. wg show should list your peer, and once the client connects you will see a recent handshake timestamp. For phones, the official WireGuard app can import the client config from a QR code: apt install qrencode, then qrencode -t ansiutf8 < client.conf.
One gotcha catches almost everyone: a successful handshake in wg show does not mean traffic flows. WireGuard is UDP-based and nearly silent, so a client with a wrong AllowedIPs or a server missing IP forwarding will show a healthy handshake while every ping fails. When that happens, check three things in order — does the client reach 10.10.0.1, is net.ipv4.ip_forward set to 1, and are the NAT rules from PostUp actually loaded (iptables -t nat -L POSTROUTING). It is almost never the crypto.
Operating it well
The biggest operational mistakes are usually not cryptographic. They are boring network problems:
- forgetting to open UDP on the firewall
- not enabling IP forwarding
- missing NAT or forwarding rules when reaching the LAN or internet through the tunnel
- using overlapping private subnets between home, office, and cloud networks
- misconfiguring DNS so resources resolve differently on and off the tunnel
If your goal is home lab access, keep the first version small. Confirm that a client can connect to the WireGuard server itself. Then test a second hop, such as a NAS or internal web UI. Then add DNS. Then decide whether full-tunnel routing is worth it. Doing everything at once makes debugging much harder.
Security posture matters too. WireGuard is not a substitute for host hardening. Keep the VPN server patched, minimize exposed services, follow the basics in our SSH hardening guide, and treat the private keys as sensitive credentials. If a device is lost, remove its peer entry and rotate keys if your risk model requires it. WireGuard does not have the same certificate and account management style as some older VPNs, which is part of its appeal, but that also means you need a clean process for peer lifecycle management.
Mobile support is another reason WireGuard is popular. The official clients are good, QR-based onboarding is convenient, and roaming between networks works well in practice. That makes it excellent for administrators who need reliable access from laptops and phones without babysitting a fragile VPN stack.
For public cloud servers, WireGuard is often best used as a private management plane rather than as a workaround for weak security on the public interface. The server should still have a proper firewall, key-based SSH, and minimal attack surface. WireGuard gives you a cleaner path for administration; it should not become an excuse to expose sloppy infrastructure.
My recommendation is to use WireGuard when you want a small, understandable VPN that you can actually maintain. Start with a narrow objective, use fixed tunnel addresses, document your routes, and test failure scenarios like key rotation and server reboot. In a self-hosted environment, reliability comes from boring clarity more than from feature count.
If you are supporting other people, write down the recovery basics: where the server config lives, which port is exposed, what tunnel subnet you chose, and how to add or revoke a peer. A self-hosted VPN is most useful when it is not trapped inside one admin's memory.
Sources
This article is for general information only and should not be treated as professional advice.