WireGuard is the VPN protocol that changed everything. It runs in kernel space on Linux, uses ~4,000 lines of code (vs OpenVPN’s 400,000+), and delivers 2-3x better performance with lower CPU and battery usage. Since its inclusion in the Linux kernel (5.6+), it’s become the foundation for every modern self-hosted VPN tool.
This guide covers three ways to set up WireGuard, from manual to fully managed:
- Manual WireGuard on Ubuntu — full control, learn the internals
- WG-Easy with Docker — web UI, five-minute setup
- NetBird — mesh networking, zero-trust, and WireGuard without the config files
Start with whichever matches your needs. If you’re learning, go manual. If you need a working VPN fast, go WG-Easy. If you’re building for a team, skip straight to NetBird.
Prerequisites
You’ll need:
- A server with a public IP address (VPS, cloud instance, or home server with port forwarding)
- Ubuntu 22.04 or newer (other Linux distros work, but commands may differ)
- Root or sudo access
- UDP port 51820 open in your firewall
Where to host: Any VPS provider works. If you want a free option, Oracle Cloud’s free tier gives you a VM with a public IP at no cost — more than enough for a WireGuard server.
Option 1: Manual WireGuard Setup on Ubuntu
This is the “learn how it works” approach. You’ll understand every piece of the puzzle.
Step 1: Install WireGuard
sudo apt update && sudo apt install wireguard -y
WireGuard is included in the default Ubuntu repositories since 22.04. The kernel module loads automatically.
Step 2: 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
This generates a private/public key pair. The private key never leaves the server.
Step 3: Create Server Configuration
sudo nano /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <paste-server-private-key>
Address = 10.0.0.1/24
ListenPort = 51820
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 = <client-public-key>
AllowedIPs = 10.0.0.2/32
Replace eth0 with your server’s main network interface (check with ip route | grep default).
Step 4: Enable IP Forwarding
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Step 5: Start WireGuard
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
Verify it’s running:
sudo wg show
You should see the interface with your public key, listening port, and any connected peers.
Step 6: Generate Client Keys and Config
On your client machine (or on the server, then transfer the config):
wg genkey | tee client_private.key | wg pubkey > client_public.key
Create the client config file:
[Interface]
PrivateKey = <client-private-key>
Address = 10.0.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = <server-public-key>
Endpoint = your-server-ip:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Add the client’s public key to the server’s wg0.conf as a [Peer] block (shown in Step 3), then reload:
sudo systemctl restart wg-quick@wg0
Step 7: Connect
Import the client config into the WireGuard app (available for Windows, macOS, iOS, Android, Linux) and activate. You should see a handshake in sudo wg show on the server.
Manual Setup: Pros and Cons
Pros: Full understanding of the protocol. No dependencies. Minimal resource usage. Total control.
Cons: Adding peers means editing config files and restarting. No web UI. No access policies. No peer discovery. Managing 10+ peers this way becomes tedious fast.
Option 2: WG-Easy with Docker (Recommended for Simple Setups)
WG-Easy wraps WireGuard in a Docker container with a clean web UI for managing peers. It’s the sweet spot between manual setup and full mesh networking.
Step 1: Install Docker
If you don’t have Docker yet:
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
For a deeper understanding of Docker and Docker Compose, check out our Docker deep dive.
Step 2: Run WG-Easy
docker run -d \
--name wg-easy \
-e LANG=en \
-e WG_HOST=your-server-ip-or-domain \
-e PASSWORD_HASH='<your-bcrypt-hash>' \
-e WG_DEFAULT_DNS=1.1.1.1 \
-v ~/.wg-easy:/etc/wireguard \
-p 51820:51820/udp \
-p 51821:51821/tcp \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
--sysctl="net.ipv4.ip_forward=1" \
--restart unless-stopped \
ghcr.io/wg-easy/wg-easy
Generate a password hash with:
docker run ghcr.io/wg-easy/wg-easy wgpw 'YOUR_PASSWORD'
Step 3: Access the Web UI
Open http://your-server-ip:51821 in your browser. Log in with the password you set.
From here, you can:
- Create new clients with one click
- Download client configs or scan QR codes
- See connection status for each peer
- Enable/disable peers
That’s it. You have a production-ready WireGuard VPN with a management interface.
WG-Easy: Pros and Cons
Pros: Five-minute setup. Web UI for managing peers. QR codes for mobile clients. Docker makes deployment and updates trivial.
Cons: Still client-server (hub-and-spoke). No mesh networking. No access policies beyond “connected or not.” Not ideal for teams that need identity-based access control.
Option 3: NetBird (When You Need More Than a Tunnel)
If you’ve read through the manual setup and WG-Easy sections, you’ll notice a pattern: as your needs grow beyond “one tunnel, a few peers,” the configuration overhead grows with it. Access policies, peer management, identity integration, multi-site connectivity — none of that comes free with raw WireGuard or WG-Easy.
NetBird handles all of this. It uses WireGuard under the hood, but abstracts away the pain: key generation, IP assignment, NAT traversal, peer discovery, and access policies. You get WireGuard’s performance with a management layer built for teams.
Quick Start (Cloud — Free Tier)
- Sign up at netbird.io (no credit card required)
- Install the agent on your first device:
curl -fsSL https://pkgs.netbird.io/install.sh | sh
sudo netbird up
- Authenticate in the browser when prompted
- Install on a second device and repeat
- Both devices can now reach each other directly by NetBird IP or hostname
Total time: under five minutes. Both devices are connected peer-to-peer through WireGuard, with NAT traversal handled automatically.
Why Choose NetBird Over Manual WireGuard
| Feature | Manual WireGuard | WG-Easy | NetBird |
|---|---|---|---|
| Peer-to-peer mesh | No | No | Yes |
| Web management UI | No | Yes | Yes (Control Center) |
| Access policies | No | No | Yes (zero-trust) |
| SSO/OIDC | No | No | Yes |
| NAT traversal | Manual | Manual | Automatic |
| SSH key management | Manual | Manual | Identity-based |
| CLI/API automation | No | No | Yes |
| Adding a new peer | Edit config, restart | Click in web UI | Install agent, authenticate |
| Self-hostable | Yes | Yes | Yes (all components) |
For a single tunnel to your home lab, WG-Easy is perfect. For a team, a business, or anything that needs access policies and automation, NetBird is the right tool.
Read our full NetBird review for a detailed look at the platform.
Troubleshooting Common Issues
Handshake Not Completing
Most common cause: UDP port 51820 isn’t open. Check:
sudo ufw status
# or
sudo iptables -L -n | grep 51820
Also verify your cloud provider’s security group allows UDP 51820 inbound.
Peers Can Connect but Can’t Reach the Internet
IP forwarding isn’t enabled, or the MASQUERADE rule is wrong:
# Check IP forwarding
sysctl net.ipv4.ip_forward
# Should return: net.ipv4.ip_forward = 1
# Check NAT rules
sudo iptables -t nat -L POSTROUTING
Make sure the interface in your PostUp/PostDown rules matches your server’s actual network interface.
DNS Not Working Through the Tunnel
Set DNS explicitly in the client config:
DNS = 1.1.1.1, 8.8.8.8
Some Linux distributions require resolvconf installed for WireGuard’s DNS settings to take effect:
sudo apt install resolvconf
Connection Drops Behind NAT
Add PersistentKeepalive = 25 to the [Peer] section in the client config. This sends a keepalive packet every 25 seconds, preventing NAT timeouts.
Conclusion
WireGuard is the best VPN protocol available in 2026. The question is how much abstraction you want on top of it.
Manual setup teaches you how WireGuard works. Valuable for learning, viable for personal use, but doesn’t scale well.
WG-Easy is the sweet spot for personal and home lab VPN. One Docker command, a web UI, and you’re done.
NetBird is where WireGuard meets the needs of real IT teams. Mesh networking, zero-trust access, CLI/API automation, and a management interface that makes distributed networking manageable.
Pick the level that matches your needs. All three give you WireGuard’s speed, security, and simplicity.
For the full VPN landscape, see our guide to the best self-hosted VPN solutions in 2026. For protocol details, read our WireGuard vs OpenVPN comparison.