Install ZeroTier VPN on VPS — Build Your Private SDN
ZeroTier is a Software-Defined Networking (SDN) solution that connects every device as if they share the same local network — regardless of physical location. It uses end-to-end encrypted UDP with automatic NAT traversal, so there's no need to open ports or configure complex firewall rules.
Unlike WireGuard or OpenVPN, ZeroTier creates a true mesh network where every node communicates directly with each other, bypassing a central relay whenever possible. The free plan supports up to 25 nodes.
How ZeroTier Works
ZeroTier's architecture has three layers:
- Planet / Moon — root servers used for initial bootstrapping (managed by ZeroTier Inc., or self-hosted as a Moon)
- Network Controller — centralized system that issues policies, IP addresses, and ACLs (managed via my.zerotier.com or self-hosted)
- Node — the ZeroTier process running on each device, establishing direct P2P tunnels
| Feature | ZeroTier | WireGuard | Tailscale |
|---|---|---|---|
| Model | Mesh SDN | Point-to-point | Mesh (WireGuard-based) |
| NAT traversal | Automatic | Manual setup | Automatic |
| Free nodes | 25 | Unlimited (self-host) | 3 users |
| Self-host controller | Yes (ZeroTierOne) | Fully | Via Headscale |
| Setup complexity | Very easy | Moderate | Easy |
Install ZeroTier on Ubuntu/Debian VPS
Prerequisites: a ZeroTier account at my.zerotier.com and a Network ID created (or a self-hosted controller).
Step 1: Install ZeroTier
# Ubuntu / Debian (official installer)
curl -s https://install.zerotier.com | sudo bash
# Check service status
sudo systemctl status zerotier-one
sudo zerotier-cli status
# Expected output
# 200 info <NodeID> 1.14.0 ONLINE
Step 2: Join a Network
# Replace <NETWORK_ID> with your 16-digit network ID from my.zerotier.com
sudo zerotier-cli join <NETWORK_ID>
# Example
sudo zerotier-cli join 8056c2e21c000001
# Check network status
sudo zerotier-cli listnetworks
my.zerotier.com → Members → click the Authorize checkbox for the node before it receives an IP address.Step 3: Verify the Assigned IP
# Show assigned IP from the ZeroTier network
sudo zerotier-cli listnetworks
# 200 listnetworks 8056c2e21c000001 MyNetwork 72:cc:... OK PRIVATE ztXXXXXXXX 10.147.17.1/24
# Show interface details
ip addr show ztXXXXXXXX
Step 4: Test Connectivity
# Ping from another node (use the ZeroTier IP of the VPS)
ping 10.147.17.1
# SSH over the ZeroTier IP
ssh [email protected]
Configure IP Routing — Use VPS as Gateway
To route all traffic from other nodes through the VPS (acting as a VPN gateway):
Enable IP Forwarding on VPS
# Enable IPv4 forwarding
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Set up NAT (replace eth0 with your actual interface)
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i ztXXXXXXXX -j ACCEPT
sudo iptables -A FORWARD -o ztXXXXXXXX -m state --state RELATED,ESTABLISHED -j ACCEPT
# Persist iptables rules
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
Add a Managed Route in ZeroTier Dashboard
# In my.zerotier.com → Network → Settings → Managed Routes
# Add:
# Destination: 0.0.0.0/0
# Via: 10.147.17.1 ← ZeroTier IP of the VPS gateway
Self-Host the ZeroTier Network Controller
For full control over the control plane without relying on my.zerotier.com, you can run the controller on your own VPS:
Install ztncui (Web UI for ZeroTier Controller)
# Install Node.js first
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Install ztncui globally
sudo npm install -g ztncui
ztncui
# Or use Docker
docker run -d --name ztncui \
-p 3000:3000 \
-v /var/lib/zerotier-one:/var/lib/zerotier-one \
-e NODE_ENV=production \
key-networks/ztncui
Create a Network on the Self-Hosted Controller
# Get your VPS NodeID
sudo zerotier-cli info
# 200 info abcdef1234 1.14.0 ONLINE
# Create a network via the ZeroTier API
curl -s -H "X-ZT1-AUTH: $(sudo cat /var/lib/zerotier-one/authtoken.secret)" \
-X POST http://localhost:9993/controller/network/abcdef1234______
# Format: controller_nodeid + 6 underscores/zeros, then fill in config
ZeroTier with Docker Networks
Connect containers across multiple VPS instances without complex overlay network setups:
# Run ZeroTier inside a container
docker run -d \
--name zerotier \
--cap-add NET_ADMIN \
--cap-add SYS_ADMIN \
--device /dev/net/tun \
-v /var/lib/zerotier-one:/var/lib/zerotier-one \
zerotier/zerotier:latest
# Join the network
docker exec zerotier zerotier-cli join <NETWORK_ID>
# Check assigned IP
docker exec zerotier zerotier-cli listnetworks
Verify ZeroTier is Working Correctly
# Check service status
sudo systemctl status zerotier-one
# Check node status and version
sudo zerotier-cli status
# List all joined networks
sudo zerotier-cli listnetworks
# List connected peers
sudo zerotier-cli listpeers
# Show ZeroTier interface
ip addr show | grep zt
# Test ping over ZeroTier IP
ping -c 4 10.147.17.X
# Check routes
ip route | grep zt
Troubleshooting Common Issues
Error: "zerotier-cli: unable to connect to ZeroTier service"
The service is not running or the socket is not ready.
# Start the service
sudo systemctl start zerotier-one
sudo systemctl enable zerotier-one
# If still failing, remove the lock file and restart
sudo rm -f /var/lib/zerotier-one/*.lck
sudo systemctl restart zerotier-one
Node joined but received no IP address
The node must be manually authorized in the ZeroTier dashboard.
# Check network status
sudo zerotier-cli listnetworks
# If you see ACCESS_DENIED or REQUESTING_CONFIG, authorization is pending
# Go to my.zerotier.com → select network → Members
# Find the NodeID and tick the Auth checkbox
Peers show RELAY causing high latency
UDP port 9993 is blocked by the firewall.
# Open port 9993 UDP
sudo ufw allow 9993/udp
# Or with iptables
sudo iptables -A INPUT -p udp --dport 9993 -j ACCEPT
# Verify peers show DIRECT after opening the port
sudo zerotier-cli listpeers | grep DIRECT
Error: "Unable to configure virtual network port"
The tun kernel module is not loaded.
# Load the tun module
sudo modprobe tun
echo 'tun' | sudo tee -a /etc/modules
# Verify
lsmod | grep tun
Cannot ping between nodes
Managed Routes or client Allow flags are not configured.
# Check that the network has a subnet covering your nodes
sudo zerotier-cli listnetworks
# On client, check allow flags
sudo zerotier-cli set <NETWORK_ID> allowGlobal=true
sudo zerotier-cli set <NETWORK_ID> allowDefault=true
Frequently Asked Questions
Is ZeroTier secure enough for production use?
ZeroTier uses Curve25519 for key exchange and AES-256-GCM for traffic encryption — security comparable to WireGuard. For production, consider self-hosting the network controller to avoid depending on ZeroTier Inc., and deploy a private Moon to bootstrap without going through the company's planet servers.
How does ZeroTier differ from Tailscale?
Both are mesh VPNs, but Tailscale uses WireGuard as its transport layer for slightly better performance. ZeroTier uses its own SDN-focused protocol with native Layer 2 bridging support — something Tailscale doesn't offer. Tailscale's free tier is limited to 3 users while ZeroTier allows 25 nodes for free.
Does ZeroTier work on Raspberry Pi or ARM devices?
Yes — ZeroTier supports ARM, ARM64, MIPS, and x86. The same installer script works on Raspberry Pi OS, Armbian, and Ubuntu ARM without any modifications.