Running your own VPN server used to mean hand-editing WireGuard peer files and keeping track of which private key lives on which laptop. The management layers built on top of WireGuard have mostly solved that, but they move fast enough that setup guides rot: WG-Easy v15 replaced its PASSWORD_HASH environment variable with a first-run setup wizard, Headscale renamed its core config keys, and NetBird moved its server to AGPLv3 and now ships its own identity provider. The first version of this guide had all three wrong.
The short answer, as of October 2026: WG-Easy for a personal VPN with a web UI on one VPS, Headscale for a mesh across homelab and cloud machines, NetBird for teams that need SSO and access policies, AmneziaVPN where WireGuard traffic gets blocked, and plain WireGuard for scripted infrastructure. Versions, licenses and star counts below were checked against each project on October 4, 2026, and the WireGuard, WG-Easy and Headscale commands were run against those releases on Docker 28.4.
Why Self-Host Your VPN?
A commercial VPN gives you a client-to-server tunnel through someone else's network, under their logging policy. Self-hosting makes sense in three cases. You need to know exactly where traffic is routed and logged, for a SOC 2 or HIPAA audit for example. You are connecting machines across clouds, a homelab and laptops, which calls for a peer-to-peer mesh rather than a hub. Or you are on a network that throttles or blocks standard VPN traffic.
The tradeoff is operational: you patch the server, rotate keys and own the outage. If you are comfortable with a Linux VPS and Docker, that cost is small.
Quick Comparison
Versions, licenses and GitHub stars as of October 4, 2026.
| Tool | Latest Version | License | Web UI | Mesh Networking | GitHub Stars | Best For |
|---|---|---|---|---|---|---|
| WireGuard | In Linux since kernel 5.6 | GPL-2.0 | No | Manual only | - | Bare-metal, scripted setups |
| WG-Easy | v15.4.0 | AGPL-3.0 | Yes | No | 27k | Personal VPN, homelabs |
| Headscale | v0.29.4 | BSD-3-Clause | Community UIs only | Yes | 44k | Dev teams, cross-cloud mesh |
| NetBird | v0.80.0 | BSD-3 client, AGPL-3.0 server | Yes | Yes | 30k | Teams needing SSO and access policies |
| AmneziaVPN | 5.0.3.0 | GPL-3.0 | Desktop and mobile app | No | 15k | Censorship circumvention |
Deep Dive: The Top Five Self-Hosted VPN Tools
1. WireGuard - The Protocol That Changed Everything

WireGuard is not a VPN application in the traditional sense - it is a tunnel protocol, built into the Linux kernel since 5.6, and every other tool on this list either runs on it or offers it. Understanding it gives you the mental model for all of them.
The design goal is minimalism. The WireGuard paper puts the Linux implementation at under 4,000 lines of code, small enough to audit. Configuration is a keypair per peer, an exchange of public keys and a list of allowed IPs. There are no certificates, no CA and no cipher negotiation to get wrong: WireGuard uses the Noise protocol framework with Curve25519, ChaCha20, Poly1305, BLAKE2, SipHash24 and HKDF, and none of it is configurable.
The deliberate limitation is that raw WireGuard has no management layer: no user database, no web interface, no dynamic IP assignment. You configure peers statically in a .conf file. That is fine for point-to-point tunnels or scripted infrastructure; past a handful of users, use one of the tools below.
Basic server setup (Ubuntu or Debian, tested on Ubuntu 24.04):
Bashsudo apt-get update && sudo apt-get install -y wireguard # Generate server and client keypairs, readable only by you umask 077 wg genkey | tee server_private.key | wg pubkey > server_public.key wg genkey | tee client_private.key | wg pubkey > client_public.key # Let the server forward client traffic echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf sudo sysctl --system # Server config (replace eth0 with your public interface from `ip route`) sudo bash -c "cat > /etc/wireguard/wg0.conf" << EOF [Interface] Address = 10.0.0.1/24 ListenPort = 51820 PrivateKey = $(cat 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 [Peer] PublicKey = $(cat client_public.key) AllowedIPs = 10.0.0.2/32 EOF sudo wg-quick up wg0 sudo systemctl enable wg-quick@wg0
2. WG-Easy - WireGuard with a Web Interface in One Docker Command

WG-Easy packages WireGuard and a web admin UI into one container. It generates keys, writes peer configs and shows a QR code for the iOS and Android apps, so you never touch WireGuard syntax.
Version 15 is a complete rewrite and a real step up. It has user accounts with 2FA, OIDC login (Google, GitHub, Authelia, Authentik), client expiration, one-time links for handing out a config, per-client firewall rules and Prometheus metrics. It is still hub-and-spoke: every client tunnels to your server, which is what you want for a personal VPN on a small VPS and not what you want for machine-to-machine traffic.
The upgrade trap: v15 ignores the PASSWORD_HASH, SERVERURL and WG_DEFAULT_* environment variables that v14 tutorials use. Setup now happens in a wizard on first launch, or through INIT_* variables for unattended installs, and v14 users import their wg0.json backup in that wizard (migration guide). armv6 and armv7 hosts cannot move to v15.
Deploy with the official Docker Compose file:
Bashsudo mkdir -p /etc/docker/containers/wg-easy sudo curl -o /etc/docker/containers/wg-easy/docker-compose.yml \ https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml cd /etc/docker/containers/wg-easy sudo docker compose up -d
Open http://your-server:51821 and the wizard asks for an admin username and password, then the public host and port clients will connect to. One catch: v15 expects HTTPS in front of the web UI. Either put Caddy or Traefik in front (the docs have a guide for each) or, for LAN-only access, uncomment environment: in the compose file and set INSECURE=true, which the docs flag as insecure.
3. Headscale - Self-Hosted Tailscale for Mesh Networking

Headscale is an open-source reimplementation of the Tailscale control plane. Tailscale is a mesh VPN that uses WireGuard for the data plane plus a coordination server for peer discovery, NAT traversal and key exchange. Tailscale's own coordination server is closed-source and cloud-hosted; Headscale replaces it with one you run, while your devices keep using the official Tailscale clients.
Devices connect peer-to-peer once the coordination server introduces them. A laptop in Chicago and a server in us-east-1 talk directly, so your VPS never becomes a bandwidth bottleneck. That makes Headscale the default pick for a homelab or a dev team spread across cloud providers.
Two things to know. There is no official web UI: Headscale is CLI-first, and its docs list community front ends such as Headplane and headscale-ui. And the config format changed. Older guides use ip_prefixes, dns_config and db_type, which current releases replaced with prefixes, dns and database, so start from the example config for your exact version instead of copying a snippet.
Deploy Headscale with Docker (run against v0.29.4):
Bashmkdir -p ./headscale/{config,lib} && cd ./headscale # Start from the example config for your version, then set your public URL curl -o config/config.yaml \ https://raw.githubusercontent.com/juanfont/headscale/v0.29.4/config-example.yaml sed -i 's#^server_url: .*#server_url: https://headscale.yourdomain.com#; s#^listen_addr: .*#listen_addr: 0.0.0.0:8080#' config/config.yaml docker run -d --name headscale --read-only \ --tmpfs /var/run/headscale \ -v "$(pwd)/config:/etc/headscale:ro" \ -v "$(pwd)/lib:/var/lib/headscale" \ -p 127.0.0.1:8080:8080 \ docker.io/headscale/headscale:0.29.4 serve
Port 8080 is bound to localhost on purpose: put Caddy or nginx in front to terminate TLS for headscale.yourdomain.com. If startup fails with "server_url cannot be part of base_domain", set dns.base_domain in the config to a name that is not a parent of your server URL.
Create a user and an auth key:
Bashdocker exec headscale headscale users create myteam docker exec headscale headscale users list # note the numeric ID docker exec headscale headscale preauthkeys create --user 1 --reusable --expiration 24h
Current docs specify the user's numeric ID for --user here, not the name.
Connect a device (on the client machine, with Tailscale installed):
Bashsudo tailscale up --login-server=https://headscale.yourdomain.com --authkey=<your-auth-key>
Every machine in the network can then reach every other by its 100.x.x.x address, with no port forwarding.
4. NetBird - Zero-Trust Mesh Networking for Teams

NetBird is for when Headscale is not enough: you need group-based access policies, SSO, network segmentation and an activity log. It builds the same kind of WireGuard peer-to-peer mesh, then adds a management dashboard and integrations with Keycloak, Authentik, Okta, Microsoft Entra ID, Google Workspace and other identity providers.
Access is deny-by-default. You write explicit policies such as "engineering can reach the production database subnet" or "contractors can reach staging only", the posture teams used to buy a commercial zero-trust network access (ZTNA) product for.
Check the license against your use. The client and most of the repository are BSD-3-Clause, but the management/, signal/, relay/ and combined/ directories, which make up the server you self-host, are AGPL-3.0. AGPL's source-sharing obligations apply if you modify the server and let others use it over a network. NetBird also sells a cloud-hosted version if you would rather not run the server at all.
Deploy the NetBird server. You need a Linux VM with at least 1 CPU and 2GB of RAM, a public domain pointing at it, TCP 80 and 443 plus UDP 3478 open, Docker Compose, jq and curl. The current quickstart script uses NetBird's embedded Dex identity provider and a bundled Traefik for Let's Encrypt certificates, replacing the older Zitadel-based script:
Bashcurl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bash
Install and connect the client on each peer:
Bashcurl -fsSL https://pkgs.netbird.io/install.sh | sh netbird up --management-url https://netbird.yourdomain.com
netbird up opens a browser for SSO login. The dashboard then shows every peer, its status and the network topology.
5. AmneziaVPN - Obfuscated VPN for Restrictive Environments

AmneziaVPN addresses a problem the others ignore: networks that fingerprint and drop WireGuard traffic with deep packet inspection, which happens in several countries and on some corporate networks.
Its answer is protocol choice. Alongside standard WireGuard and OpenVPN it offers AmneziaWG, a modified WireGuard that resists traffic detection while keeping WireGuard performance, and Xray Reality, which the project says works even in China, Iran and Turkmenistan. The free, GPL-3.0 client runs on Windows, macOS, Linux, iOS and Android, with split tunneling and a kill switch. You pay only for the VPS.
Setup is unusually easy because the app installs the server for you over SSH. Amnezia asks for a KVM-virtualized VPS with a public IPv4 address, at least 1GB of RAM and no control panel preinstalled.
- Install AmneziaVPN on your computer.
- Choose I have connection details, then Self-hosted VPN.
- Enter the server's IP address, SSH login and password.
- Pick a protocol: AmneziaWG for speed with obfuscation, Xray Reality for the most hostile networks.
- The app connects over SSH, then installs and configures the server components.
- Share access with QR codes or config files from the app.
What Is a Good WireGuard Alternative?
If WireGuard itself is the problem rather than its management, there are three realistic alternatives, each fixing a different limitation:
- OpenVPN (2.7.7 as of October 2026) can run over TCP on port 443, which gets through networks that drop UDP. The cost is a certificate PKI to manage and more configuration than WireGuard.
- Nebula (v1.11.2, MIT), built at Slack, is a peer-to-peer overlay on the Noise protocol framework rather than WireGuard. You run your own certificate authority and "lighthouse" discovery nodes, and it is designed to connect tens of thousands of hosts.
- AmneziaWG, covered above, keeps WireGuard's design but disguises the traffic. Each device needs an AmneziaWG-capable client.
Choosing the Right Tool
For a personal VPN with a web UI on one Ubuntu or Debian server, routing your home or travel traffic through a VPS you control, WG-Easy is the answer. It has the lowest operational overhead here and needs no WireGuard knowledge.
For a homelab or machines spread across networks (cloud VMs, a home server, laptops, remote workers), Headscale gives you Tailscale's mesh without the cloud coordination dependency, and inter-device traffic never passes through your VPS.
For a team that needs access control and SSO, NetBird is the right architecture. It is the heaviest of the five to run, and the only one built around identity-based policies.
For networks that actively block VPN traffic, AmneziaVPN with AmneziaWG or Xray Reality is built for exactly that.
For scripted infrastructure where you want every config line under version control, plain WireGuard is still the right answer.
Conclusion
Four of these five run on WireGuard, and AmneziaVPN offers it, so the choice is about the management layer, not the cryptography. If you are starting fresh, run WG-Easy on a small VPS for a week. That will tell you whether you need Headscale's mesh, NetBird's access control or Amnezia's obfuscation, and moving from a plain WireGuard setup to any of them is straightforward.
Pin versions when you deploy. WG-Easy and Headscale have both shipped breaking configuration changes, and a latest tag is how a working VPN stops working after a routine restart.
Related DevToolLab Tools
- WireGuard Config Generator - Generate server and client configs with fresh key pairs and mobile QR codes in your browser, for a plain WireGuard setup without WG-Easy.
- Subnet Calculator - Check that your tunnel range (10.0.0.0/24, or Headscale's 100.64.0.0/10) does not overlap a LAN or VPC you need to reach.
- Port Checker - Confirm TCP 80 and 443 are reachable on the VM before running the NetBird installer.
- DNS Lookup - Verify that
headscale.yourdomain.comornetbird.yourdomain.comresolves to your server before requesting a certificate.
Related Guides
- 11 Best Ngrok Alternatives - when you need to expose one service publicly rather than join a private network
- 11 Free Playit.gg Alternatives - tunnels for game servers behind CGNAT
- How to Generate an SSH Key - key-based SSH for the VPS that hosts your VPN
- Best Uptime Monitoring Tools - get alerted when the VPN host goes down
