ZeroTier Virtual Network Configuration

ZeroTier is a software-defined networking platform that creates virtual Layer 2 networks over the internet using peer-to-peer connectivity, making it a powerful VPN alternative for connecting VPS instances, bare-metal servers, and remote devices. Unlike traditional VPNs, ZeroTier handles NAT traversal automatically and allows you to build complex network topologies without dedicated gateway hardware.

Prerequisites

  • Ubuntu 20.04+, Debian 11+, CentOS 8+, or Rocky Linux 8+
  • Root or sudo access
  • A ZeroTier account at my.zerotier.com (free for up to 25 devices)
  • Outbound UDP access (port 9993)

Installing ZeroTier

Ubuntu/Debian:

# Install using the official script
curl -s https://install.zerotier.com | sudo bash

# Or manually via APT
curl -s 'https://raw.githubusercontent.com/zerotier/ZeroTierOne/main/doc/contact%40zerotier.com.gpg' | \
  gpg --dearmor | sudo tee /usr/share/keyrings/zerotierone-archive-keyring.gpg > /dev/null

echo "deb [signed-by=/usr/share/keyrings/zerotierone-archive-keyring.gpg] \
  http://download.zerotier.com/debian/bookworm bookworm main" | \
  sudo tee /etc/apt/sources.list.d/zerotier.list

sudo apt update && sudo apt install -y zerotier-one

CentOS/Rocky Linux:

# Install and enable
sudo dnf install -y zerotier-one
sudo systemctl enable --now zerotier-one
# Verify the service is running
sudo systemctl status zerotier-one

# Get this node's ZeroTier address
sudo zerotier-cli info
# Output: 200 info <node-id> <version> ONLINE

Creating and Joining a Network

Create a network in the web interface:

  1. Log into https://my.zerotier.com
  2. Click Create A Network — a unique 16-character network ID is generated
  3. Note the Network ID (e.g., 8056c2e21c000001)

Join the network from each node:

# Join using the network ID
sudo zerotier-cli join 8056c2e21c000001

# Check join status
sudo zerotier-cli listnetworks

# Leave a network
sudo zerotier-cli leave 8056c2e21c000001

List all joined networks and their status:

sudo zerotier-cli listnetworks
# Output shows network ID, name, MAC, IP, status, type

Member Authorization and IP Assignment

By default, new members require manual authorization unless you enable open access.

Authorize members via CLI (using API token):

# Get your API token from my.zerotier.com/account
ZT_TOKEN="your_api_token"
NETWORK_ID="8056c2e21c000001"
NODE_ID="abc123def456"

# Authorize a member
curl -X POST "https://api.zerotier.com/api/v1/network/${NETWORK_ID}/member/${NODE_ID}" \
  -H "Authorization: token ${ZT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"config": {"authorized": true}}'

Configure IP assignment pools:

In the ZeroTier Central UI under Advanced > Managed Routes and IP Assignment, add an assignment pool:

IP Range: 10.147.17.1 - 10.147.17.254
Route:    10.147.17.0/24 → (leave empty for local)
# Verify assigned IP on the node
sudo zerotier-cli listnetworks | grep -i ip
ip addr show zt+    # Show ZeroTier interface

Routing and Bridging

Add a managed route to reach LAN subnets:

In ZeroTier Central, under the network's Routes section, add:

Destination: 192.168.1.0/24
Via:         10.147.17.5    # IP of the node connected to that LAN

Enable IP forwarding on the routing node:

# Enable forwarding permanently
sudo tee /etc/sysctl.d/99-zerotier.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
EOF
sudo sysctl -p /etc/sysctl.d/99-zerotier.conf

# Allow forwarding between ZeroTier and LAN interfaces
sudo iptables -A FORWARD -i zt+ -j ACCEPT
sudo iptables -A FORWARD -o zt+ -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# Make iptables rules persistent
sudo apt install -y iptables-persistent
sudo netfilter-persistent save

Layer 2 bridging (connect ZeroTier to physical LAN):

# Install bridge utilities
sudo apt install -y bridge-utils

# Create a bridge between ZeroTier and LAN interface
sudo ip link add br0 type bridge
sudo ip link set zt3jnwgqos master br0
sudo ip link set eth0 master br0
sudo ip link set br0 up

Firewall Rules

ZeroTier networks support built-in traffic rules in the Flow Rules section of the network:

# Drop traffic between members (default deny)
drop not ethertype ipv4 and not ethertype ipv6 and not ethertype arp;

# Allow specific port (e.g., port 22 between tagged members)
accept ztdest "server" and ipprotocol tcp and dport 22;

# Allow all traffic (open network)
accept;

Host-level firewall with UFW:

# Allow ZeroTier traffic on the virtual interface
sudo ufw allow in on zt+ to any port 22
sudo ufw allow in on zt+ to any port 80
sudo ufw allow in on zt+ to any port 443

# Block direct internet access to services
sudo ufw deny 80
sudo ufw deny 443
sudo ufw enable

Self-Hosted Controller

Run your own ZeroTier controller with ztncui for air-gapped or private deployments:

# Pull and run the self-hosted controller
docker run -d \
  --name ztncui \
  -p 3000:3000 \
  -p 9993:9993/udp \
  -v /opt/zerotier:/var/lib/zerotier-one \
  -e ZTNCUI_PASSWD=admin_password \
  keynetworks/ztncui

# Get the controller node ID
docker exec ztncui zerotier-cli info

Join the self-hosted network by specifying the controller:

# Join a network hosted on your controller (network ID starts with controller node ID)
sudo zerotier-cli join <controller-node-id>______

Troubleshooting

Node shows REQUESTING_CONFIGURATION:

# Check authorization status in ZeroTier Central
# The node must be authorized before it shows as OK
sudo zerotier-cli listnetworks

# Restart ZeroTier
sudo systemctl restart zerotier-one

Cannot reach other nodes:

# Check connectivity to ZeroTier roots
sudo zerotier-cli peers

# Test ping over ZeroTier interface
ping 10.147.17.2

# Check firewall on the target node allows ZeroTier
sudo ufw status

UDP port 9993 blocked by provider:

# ZeroTier can fall back to TCP relays, but performance is degraded
# Allow outbound UDP 9993
sudo ufw allow out 9993/udp

# For providers blocking UDP, check if relay mode is active
sudo zerotier-cli peers | grep RELAY

Conclusion

ZeroTier provides a flexible software-defined networking layer that simplifies connecting distributed infrastructure without complex VPN configurations. By combining managed routes, flow rules, and IP assignment pools, you can build secure multi-site networks that span cloud providers and on-premises environments, with optional self-hosted controllers for complete infrastructure independence.