Self-hosted mesh VPN built on Headscale (open-source Tailscale control plane), Caddy (reverse proxy + auto TLS), and WireGuard (encrypted tunnels).
Deploy on a single Ubuntu VPS. Connect any device running the Tailscale client — macOS, Linux, Windows, iOS, Android. Nodes communicate directly via WireGuard P2P, falling back to an embedded DERP relay when NAT prevents direct connections.
Internet
|
+--------+--------+
| Ubuntu VPS |
| |
:80,:443 ------+| Caddy | <-- TLS termination
| | |
| Headscale | <-- Control plane + DERP relay
| | |
:3478/udp -----+| (STUN) |
| |
| Admin UI | <-- Web dashboard
+-----------------+
Client A <------ WireGuard P2P ------> Client B
| |
+------ DERP relay (fallback) ---------+
ssh root@<VPS_IP>
git clone https://github.com/kapiljain1989/meshnet.git /opt/meshnet
cd /opt/meshnet
cp .env.example .env # set HEADSCALE_DOMAIN, UI_DOMAIN, ACME_EMAIL
sudo bash scripts/deploy.shSee DEPLOYMENT_GUIDE.md for full instructions.
bash scripts/test-local.shStarts the full stack on your LAN with self-signed TLS. Prints credentials, pre-auth keys, and copy-paste commands for connecting clients.
See LOCAL_TESTING.md for details.
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Connect to your MeshNet
sudo tailscale up --login-server=https://hs.yourdomain.comdocker-compose.yml # Production stack (3 services)
docker-compose.local.yml # Local testing override
.env.example # Required environment variables
config/
caddy/Caddyfile # Reverse proxy + TLS config
caddy/Caddyfile.local # Local testing (self-signed TLS)
headscale/config.yaml # Headscale control plane config
headscale/config.yaml.local # Local testing (localhost)
headscale/acl.yaml # Access control policy
scripts/
deploy.sh # VPS bootstrap (Docker, firewall, certs)
test-local.sh # Local test runner
- Fully self-hosted — no data passes through Tailscale's servers
- Automatic TLS — Caddy provisions Let's Encrypt certificates
- Embedded DERP relay — fallback when P2P fails, on your own server
- MagicDNS — nodes get names like
laptop.admin.mesh - ACL policies — control which nodes can talk to each other
- Web admin UI — manage users, nodes, and API keys
- Daily backups — automated SQLite backups with 7-day retention
| Port | Protocol | Purpose |
|---|---|---|
| 80 | TCP | ACME HTTP-01 challenge |
| 443 | TCP+UDP | HTTPS + HTTP/3 |
| 3478 | UDP | STUN (NAT traversal) |
Private repository.