ZeroTier Cheat Sheet
Overview
ZeroTier is a smart programmable Ethernet switch for planet Earth. It creates virtual networks that connect devices across the internet as though they are on the same local network, without complex VPN configuration or firewall rules. Using a combination of a global root server infrastructure for peer discovery and direct peer-to-peer encrypted connections for data transfer, ZeroTier provides Layer 2 connectivity with near-zero configuration. Devices can join networks simply by knowing the 16-digit network ID.
ZeroTier supports all major platforms including Linux, macOS, Windows, Android, iOS, and FreeBSD, as well as NAS devices and Docker containers. It uses 256-bit encryption (Curve25519, Salsa20, Poly1305) for all peer-to-peer traffic and supports features like managed routes, DNS, flow rules for microsegmentation, and multicast. The free tier supports up to 25 devices per network, while self-hosted controllers provide unlimited nodes. Common use cases include remote access, site-to-site connectivity, IoT networks, gaming LANs, and hybrid cloud networking.
Installation
Linux
# One-line install script
curl -s https://install.zerotier.com | sudo bash
# Debian/Ubuntu
sudo apt update
sudo apt install zerotier-one
# CentOS/RHEL
sudo yum install https://download.zerotier.com/redhat/el/7/zerotier-one.rpm
# Start and enable service
sudo systemctl start zerotier-one
sudo systemctl enable zerotier-one
macOS
# Using Homebrew
brew install zerotier-one
# Or download from https://www.zerotier.com/download/
# Start service
sudo launchctl load /Library/LaunchDaemons/com.zerotier.one.plist
Windows
# Download installer from https://www.zerotier.com/download/
# Or using winget
winget install ZeroTier.ZeroTierOne
# Or using Chocolatey
choco install zerotier-one
Docker
docker run -d \
--name zerotier-one \
--device /dev/net/tun \
--net host \
--cap-add NET_ADMIN \
--cap-add SYS_ADMIN \
-v /var/lib/zerotier-one:/var/lib/zerotier-one \
zerotier/zerotier:latest
Core Commands
| Command | Description |
|---|---|
sudo zerotier-cli status | Show node status and address |
sudo zerotier-cli info | Show node ID and version |
sudo zerotier-cli join <networkId> | Join a network |
sudo zerotier-cli leave <networkId> | Leave a network |
sudo zerotier-cli listnetworks | List joined networks |
sudo zerotier-cli listpeers | List all known peers |
sudo zerotier-cli peers | Show peer details with paths |
sudo zerotier-cli get <networkId> <key> | Get network property |
sudo zerotier-cli set <networkId> <k>=<v> | Set network property |
sudo zerotier-cli dump | Dump debug info |
Joining a Network
# Join network (get network ID from my.zerotier.com)
sudo zerotier-cli join a1b2c3d4e5f67890
# Check join status (must be authorized via web UI or API)
sudo zerotier-cli listnetworks
# Output columns: network ID, name, MAC, status, type, device, IPs
# Status: OK = authorized, ACCESS_DENIED = needs authorization
Peer Information
# List peers with connection details
sudo zerotier-cli peers
# Output shows:
# LEAF = regular peer
# PLANET = root server
# Path: DIRECT = peer-to-peer, RELAY = relayed through root
# Detailed peer info
sudo zerotier-cli listpeers
Network Configuration (Web UI)
Create a Network
- Sign in at
https://my.zerotier.com - Click “Create A Network” — a 16-digit network ID is generated
- Configure settings:
- Network name
- Access control (private = manual auth, public = auto-auth)
- IPv4/IPv6 auto-assign ranges
- Managed routes
Managed Routes
# In web UI under "Managed Routes"
# Route traffic to remote subnet via ZeroTier member
Destination: 192.168.1.0/24 Via: 10.147.20.1
Destination: 10.0.0.0/8 Via: 10.147.20.5
# Default route (send all traffic through ZeroTier)
Destination: 0.0.0.0/0 Via: 10.147.20.1
Flow Rules
# /etc/zerotier/local.conf or via API
# Allow only specific traffic between members
# Default allow all
accept;
# Drop traffic between tagged groups
tag department
id 100
enum 1 engineering
enum 2 marketing
enum 3 finance
;
# Block marketing from accessing engineering
drop
tsrc department=marketing
tdst department=engineering
;
# Rate limiting
cap rate_limit
id 200
rate 10000000 # 10 Mbps
;
# Allow only SSH and HTTP
drop not chr ipauth
and not dport 22
and not dport 80
and not dport 443
;
Self-Hosted Controller
Using ztncui (Web Interface)
# Install controller
sudo apt install zerotier-one
# Install ztncui
git clone https://github.com/key-networks/ztncui.git
cd ztncui/src
npm install
# Configure
cp .env.example .env
# Edit .env:
# ZT_TOKEN=$(cat /var/lib/zerotier-one/authtoken.secret)
# NODE_ENV=production
# HTTP_PORT=3443
# Start
npm start
Controller API
# Get auth token
ZT_TOKEN=$(sudo cat /var/lib/zerotier-one/authtoken.secret)
# List networks
curl -s -H "X-ZT1-Auth: $ZT_TOKEN" http://localhost:9993/controller/network | jq
# Create network
curl -s -X POST -H "X-ZT1-Auth: $ZT_TOKEN" \
http://localhost:9993/controller/network/${NODE_ID}______ | jq
# Get network details
curl -s -H "X-ZT1-Auth: $ZT_TOKEN" \
http://localhost:9993/controller/network/<networkId> | jq
# Authorize member
curl -s -X POST -H "X-ZT1-Auth: $ZT_TOKEN" \
-d '{"authorized": true}' \
http://localhost:9993/controller/network/<networkId>/member/<memberId> | jq
# Assign IP to member
curl -s -X POST -H "X-ZT1-Auth: $ZT_TOKEN" \
-d '{"ipAssignments": ["10.147.20.10"]}' \
http://localhost:9993/controller/network/<networkId>/member/<memberId> | jq
Configuration
Local Configuration
// /var/lib/zerotier-one/local.conf
{
"physical": {
"0.0.0.0/0": {
"blacklist": false,
"trustedPathId": 0
}
},
"virtual": {
"feedbeef01": {
"try": ["10.0.0.5/9993"],
"blacklist": []
}
},
"settings": {
"primaryPort": 9993,
"portMappingEnabled": true,
"softwareUpdate": "disable",
"allowTcpFallbackRelay": true,
"interfacePrefixBlacklist": ["docker", "veth"]
}
}
Gateway Configuration (Route All Traffic)
# On the gateway node (Linux)
# Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
# NAT ZeroTier traffic to physical interface
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i zt+ -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o zt+ -m state --state RELATED,ESTABLISHED -j ACCEPT
# Save iptables rules
sudo apt install iptables-persistent
sudo netfilter-persistent save
Advanced Usage
DNS Configuration
# Set DNS via API
curl -s -X POST -H "X-ZT1-Auth: $ZT_TOKEN" \
-d '{
"dns": {
"domain": "zt.example.com",
"servers": ["10.147.20.1"]
}
}' \
http://localhost:9993/controller/network/<networkId>
# Client-side: ZeroTier will push DNS to members
# Verify with:
resolvectl status zt0
Bridge Mode
# Bridge ZeroTier network to physical LAN
# On bridge node:
sudo zerotier-cli set <networkId> allowBridge=true
# Create bridge
sudo brctl addbr br0
sudo brctl addif br0 eth0
sudo brctl addif br0 zt0
sudo ip link set br0 up
Multi-Path and Bonding
// local.conf - bond multiple physical paths
{
"settings": {
"allowMultipathBonding": true
}
}
Troubleshooting
| Issue | Solution |
|---|---|
| Status shows ACCESS_DENIED | Authorize member in web UI or API |
| No direct path (RELAY only) | Check firewall allows UDP/9993, enable UPnP |
| Can’t reach remote subnet | Add managed route, enable IP forwarding on gateway |
| High latency | Check peers for RELAY vs DIRECT paths |
| Service won’t start | Check logs: journalctl -u zerotier-one |
| IP not assigned | Check auto-assign range in network settings |
| Docker container can’t join | Need —device /dev/net/tun and NET_ADMIN cap |
| Multicast not working | Enable multicast in network settings |
Diagnostic Commands
# Check service status
sudo systemctl status zerotier-one
# View logs
journalctl -u zerotier-one -f
# Check ZeroTier interface
ip addr show zt+
ifconfig zt0
# Test connectivity
ping <zt-ip-of-peer>
# Check if port is open
sudo ss -ulnp | grep 9993
# Verify direct connectivity
sudo zerotier-cli peers | grep DIRECT