私有部署zerotier-planet服务
Go to file
Anonymous fd0e04cf33 fix
2026-05-13 11:23:16 +08:00
.github/workflows fix: harden deployment defaults and file delivery 2026-05-01 20:06:48 +08:00
assets addwechat 2025-05-08 17:35:20 +08:00
patch fix 2026-05-13 11:23:16 +08:00
scripts refactor: make compose the only deployment path 2026-05-01 20:49:21 +08:00
test fix 2026-05-13 11:23:16 +08:00
.dockerignore fix: harden deployment defaults and file delivery 2026-05-01 20:06:48 +08:00
.env.example fix 2026-05-13 00:30:26 +08:00
.gitignore chore: update deployment documentation and streamline helper functions 2026-05-01 20:49:54 +08:00
build.sh fix: harden deployment defaults and file delivery 2026-05-01 20:06:48 +08:00
compose.public-http.yaml fix 2026-05-13 00:30:26 +08:00
compose.yaml fix 2026-05-13 00:30:26 +08:00
Dockerfile fix: harden deployment defaults and file delivery 2026-05-01 20:06:48 +08:00
README.en.md fix 2026-05-13 00:30:26 +08:00
README.md fix 2026-05-13 00:30:26 +08:00
SECURITY.md fix 2026-05-13 00:30:26 +08:00

🌐 Languages: English | 中文

Logo CDN acceleration and security for this project are sponsored by Tencent EdgeOne

Docker ZeroTier Planet

Deploy a ZeroTier Planet server with Docker Compose for containerized runtime and maintenance.

📢 Community

Telegram

QQ Groups

  • Group 1: 692635772
  • Group 2: 785620313
  • Group 3: 316239544
  • Group 4: 1027678459

📱 WeChat Official Account

QR Code

Features

  • Supports Linux/AMD64 and Linux/ARM64 architectures
  • 🐳 Docker containerized deployment
  • 📥 Supports downloading planet and moon configuration files via URL
  • 🌐 Can be deployed as either a Moon or Planet server
  • 🔧 Docker Compose based deployment and maintenance workflow
  • 📊 Visual, webbased management UI

📋 Table of Contents


0. Managed Hosting

0.1 Managed Container Service

Looking for a hasslefree solution?

We provide professional managed hosting:

Item Details
Trial Free 3day trial
Annual Fee ¥99 per year
Bandwidth Highspeed 300 Mbit
Traffic Policy 100 GB/month forwarded traffic; once peers connect via P2P, traffic is not counted. Beyond quota: ¥10 per additional 100 GB
Data Center Premium route: Ningbo China Telecom
Contact Telegram: https://t.me/uxkram, or join a QQ group and contact the admin

Speed test:

Ningbo DC Speed Test

0.2 Rainyun Container Service

Deploy on Rainyun

0.3 WeChat Official Account

Follow for the latest updates and technical posts:

WeChat Official Account QR

1. What Is ZeroTier?

ZeroTier is a powerful P2P VPN that lets you create your own virtual LAN over the public Internet. With it, you can easily access devices at home from anywhere—for example, reach your home NAS directly from the office or on mobile. Most importantly, devices connect peertopeer without going through a relay by default, which improves both performance and security.

How It Works

The ZeroTier One client establishes P2P connections among devices (laptops, phones, servers, etc.), even when they are all behind NAT. Using techniques such as STUN, ZeroTier can traverse most NAT types to enable direct devicetodevice communication. Only when direct connectivity fails does it fall back to relay.

Put simply, ZeroTier acts like a virtual Ethernet switch spanning the Internet, so devices distributed around the world can talk to each other as if they were on the same LAN.

zerotier

Key Concepts in a ZeroTier Network

Concept Description
PLANET (root servers) The core root servers for the ZeroTier network. They handle network discovery and initial connections—the “central hub” of the ecosystem.
MOON (private roots) Useroperated private root servers. They act as regional anchors to help nearby nodes connect faster and improve network performance.
LEAF (endpoints) All devices that join a ZeroTier network—PCs, phones, servers, etc. These endpoints discover and communicate under the coordination of PLANET and MOON.

This guide walks you through building your own private PLANET server so you have full control over your ZeroTier environment.


2. Why Run Your Own PLANET Server?

🚀 Performance

  • Higher stability: The official roots are overseas; users in mainland China may see high latency and jitter. A selfhosted PLANET can significantly improve link quality.
  • Faster setup: A local PLANET server can help nodes establish P2P connectivity more quickly.

🔒 Security

  • Full control: Maintain complete control over your network configuration and tune it for your needs.
  • Better privacy: Private deployment means your traffic does not traverse thirdparty infrastructure by default.

💪 Reliability

  • Reduced dependency: Avoid outages or fluctuations affecting the public root infrastructure.

3. Getting Started

3.1 Prerequisites

Before you begin, make sure your server meets the following:

Server

  • Public IPv4 address
  • Open these ports:
    • 3443/tcp (management UI, adjust if needed)
    • 9994/tcp (ZeroTier transport, adjust if needed)
    • 9994/udp (ZeroTier transport, adjust if needed)

Software

  • Docker (container runtime)
  • Git (to fetch the repository)

OS

A recent Linux distribution is recommended, such as:

  • Debian 12
  • Ubuntu 20.04+
  • Rocky Linux
  • Other similar distributions

3.1.1 Install Git

# Debian/Ubuntu, etc.
apt update && apt install git -y

# CentOS, etc.
yum update && yum install git -y

3.1.2 Install Docker

curl -fsSL https://get.docker.com | bash

Note: If network issues prevent installation, you can use a mainland China mirror. See: Install Docker.

3.1.3 Start Docker

service docker start

3.1.4 (Optional) Configure Docker Registry Mirrors

sudo tee /etc/docker/daemon.json <<EOF
{
    "registry-mirrors": [
        "https://docker.mirrors.aster.edu.pl",
        "https://docker.mirrors.imoyuapp.win"
    ]
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

3.2 Get the Source Code

Official repository:

git clone https://github.com/xubiaolin/docker-zerotier-planet.git

Accelerated mirror:

git clone https://github.com/xubiaolin/docker-zerotier-planet.git

3.3 Install with Docker Compose

  1. Enter the project directory:
cd docker-zerotier-planet
  1. Create and edit the config:
cp .env.example .env
vim .env

Set at least one of IP_ADDR4 or IP_ADDR6. By default, compose.yaml pins the management UI and file server to host 127.0.0.1, so accidentally changing HOST_BIND_IP to a public address does not publish plaintext HTTP.

  1. Start the service:
docker compose up -d
  1. Check access information:
docker compose ps
docker exec ${CONTAINER_NAME:-myztplanet} sh -c 'cat /app/config/ztncui.initial-password'

3.4 Download the planet File

After the script completes, the planet and moon configuration files are generated in ./data/zerotier/dist.

By default, the file download service is intended for local access or HTTPS reverse-proxy access, and the access key is sent in a request header instead of in the URL. The file service key is stored in ./data/zerotier/config/file_server.key.

Recommended retrieval methods:

  1. Download locally on the server (recommended)
    FILE_KEY=$(cat ./data/zerotier/config/file_server.key)
    curl -H "Authorization: Bearer ${FILE_KEY}" http://127.0.0.1:3000/planet -o planet
    # moon example: curl -H "Authorization: Bearer ${FILE_KEY}" http://127.0.0.1:3000/<moon-id>.moon -o <moon-id>.moon
    
  2. Use scp, SFTP, or another file transfer tool to fetch them from the server
  3. Use an HTTPS reverse proxy: configure TLS first in section 5, then use the same Authorization: Bearer header.

Security: Do not share command output containing secrets, and do not use secret-bearing query-string download links. ALLOW_QUERY_FILE_KEY=true is only a short-term compatibility bridge, is disabled by default, and is planned for removal. Important: Keep these files safe—you will need them when configuring clients.

3.5 Create a Network

3.5.1 Access the Controller UI

The default deployment binds the management UI to the host loopback address (127.0.0.1:3443) to avoid exposing plaintext HTTP on the public internet. Access it locally, through an SSH tunnel, or through a TLS reverse proxy:

ssh -L 3443:127.0.0.1:3443 <user>@<server-ip>
# Then open http://127.0.0.1:3443 in your local browser

ui

Login credentials:

  • The default username is admin (override with ZTNCUI_USER)
  • The password is no longer a public default; if ZTNCUI_BOOTSTRAP_PASSWORD or ZTNCUI_BOOTSTRAP_PASSWORD_FILE is not provided, the container generates a random password on first start
  • The generated initial password is stored at ./data/zerotier/config/ztncui.initial-password; change it after first login and store it safely
docker exec ${CONTAINER_NAME:-myztplanet} sh -c 'cat /app/config/ztncui.initial-password'

Security: Do not use public default management credentials. For public access, prefer the TLS reverse proxy. Public plaintext HTTP is only for temporary lab use and requires an explicit opt-in flag.

3.5.2 Create a Network

  1. After logging in, click Networks
  2. Click Add Network
  3. Enter a readable network name; other settings can remain at defaults
  4. Click Create Network

ui

A Network ID will be generated—record it; you will need it for client setup.

ui

3.5.3 Assign Network IPs

  1. Select Easy Setup
    assign_id

  2. Generate the IP range
    ip_addr


4. Client Configuration

ZeroTier clients are available for:

  • Windows
  • macOS
  • Linux
  • Android

4.0 One-Command Install and planet Replacement

On Windows, Linux, and macOS, the client installer scripts can install ZeroTier, download and replace planet, restart the ZeroTier service, and optionally run join when you pass a network ID.

Read the file-server key on the deployment server first:

FILE_KEY=$(cat ./data/zerotier/config/file_server.key)

PLANET_URL should normally be an HTTPS reverse-proxy URL, for example https://files.example.com/planet. The scripts reject plaintext HTTP by default; use --allow-insecure-http or -AllowInsecureHttp only for temporary private-lab testing.

Windows (Administrator PowerShell):

$PlanetUrl = "https://files.example.com/planet"
$FileKey = "replace with the contents of ./data/zerotier/config/file_server.key"
$NetworkId = "replace with your network ID, or omit it"
$Script = "$env:TEMP\install-zerotier-client.ps1"
Invoke-WebRequest "https://raw.githubusercontent.com/xubiaolin/docker-zerotier-planet/master/scripts/install-zerotier-client.ps1" -OutFile $Script
powershell -ExecutionPolicy Bypass -File $Script -PlanetUrl $PlanetUrl -FileKey $FileKey -NetworkId $NetworkId

Linux/macOS:

curl -fsSL https://raw.githubusercontent.com/xubiaolin/docker-zerotier-planet/master/scripts/install-zerotier-client.sh \
  | sudo bash -s -- \
      --planet-url "https://files.example.com/planet" \
      --file-key "${FILE_KEY}" \
      --network-id "replace with your network ID, or omit it"

The scripts download planet with an Authorization: Bearer header and do not put FILE_KEY in the URL.

4.1 Windows

The steps below are the manual fallback for troubleshooting or environments where you do not want to run the one-command installer.

Step 1: Download the Client

Download the Windows client from the official ZeroTier website.

Step 2: Replace the planet File

Copy the planet file into C:\ProgramData\ZeroTier\One (this is a hidden directory—enable “show hidden items”).

Step 3: Restart the Service

  1. Press Win + S and search for Services
    ui

  2. Locate ZeroTier One and restart it
    ui

Step 4: Join the Network

Open PowerShell as Administrator and run:

PS C:\Windows\system32> zerotier-cli.bat join <NETWORK_ID>
200 join OK
PS C:\Windows\system32>

Note: <NETWORK_ID> is the ID created in the web UI above.

Step 5: Authorize the Device

In the management UI, locate the new client and check Authorized.

ui

The assigned ZeroTier IP will appear under IP assignment.

ip

Step 6: Verify Connectivity

Run:

PS C:\Windows\system32> zerotier-cli.bat peers
200 peers
<ztaddr>   <ver>  <role> <lat> <link> <lastTX> <lastRX> <path>
fcbaeb9b6c 1.8.7  PLANET    52 DIRECT 16       8994     1.1.1.1/9993
fe92971aad 1.8.7  LEAF      14 DIRECT -1       4150     2.2.2.2/9993
PS C:\Windows\system32>

You should see both a PLANET and a LEAF peer with DIRECT links.

4.2 Linux

The steps below are the manual fallback for troubleshooting or environments where you do not want to run the one-command installer.

Steps:

  1. Install the Linux ZeroTier client
  2. Go to /var/lib/zerotier-one
  3. Replace the planet file in that directory
  4. Restart the service: service zerotier-one restart
  5. Join the network: zerotier-cli join <NETWORK_ID>
  6. Approve the join request in the management UI
  7. Run zerotier-cli peers and verify the PLANET role appears

4.3 Android

We recommend the Unofficial Android Client.

4.4 macOS

The steps below are the manual fallback for troubleshooting or environments where you do not want to run the one-command installer.

Steps:

  1. Go to /Library/Application\ Support/ZeroTier/One/ and replace the planet file
  2. Restart ZeroTierOne: cat /Library/Application\ Support/ZeroTier/One/zerotier-one.pid | sudo xargs kill
  3. Join the network: zerotier-cli join <NETWORK_ID>
  4. Approve the join request in the management UI
  5. Run zerotier-cli peers and verify the PLANET role appears

4.5 OpenWRT

Steps:

  1. Install the ZeroTier client
  2. Go to /etc/config/zero/planet
  3. Replace the planet file
  4. In the OpenWRT web UI, stop ZeroTier, then start it again
  5. Join the network from the OpenWRT web UI
  6. Approve the join request in the management UI
  7. Run ln -s /etc/config/zero /var/lib/zerotier-one
  8. Run zerotier-cli peers and verify the PLANET role appears

4.6 iOS

Option 1: Jailbreak
Install ZeroTier and replace the planet file (requires a jailbroken device).

Option 2: WireGuard
Use WireGuard to access the ZeroTier network indirectly.


5. TLS / Reverse Proxy for the Management Panel

The default deployment binds the management UI and file download service to host-local addresses (for example 127.0.0.1:3443 and 127.0.0.1:3000). If you need public access, put them behind HTTPS with valid certificates; do not expose plaintext HTTP directly.

The example below uses separate hostnames for the management UI and file downloads. Adjust it to your gateway layout as needed:

upstream zerotier_ui {
  server 127.0.0.1:3443;
}

upstream zerotier_files {
  server 127.0.0.1:3000;
}

server {
  listen 443 ssl http2;
  server_name {CUSTOM_DOMAIN}; # Management UI hostname

  ssl_certificate     <path to .pem or .crt>;
  ssl_certificate_key <path to .key>;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_prefer_server_ciphers off;

  location / {
    proxy_pass http://zerotier_ui;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

server {
  listen 443 ssl http2;
  server_name files.{CUSTOM_DOMAIN}; # File download hostname

  ssl_certificate     <path to .pem or .crt>;
  ssl_certificate_key <path to .key>;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_prefer_server_ciphers off;

  location / {
    proxy_pass http://zerotier_files;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

server {
  listen 80;
  server_name {CUSTOM_DOMAIN} files.{CUSTOM_DOMAIN};
  return 301 https://$host$request_uri;
}

Downloads through the reverse proxy still require header authentication:

FILE_KEY=$(cat ./data/zerotier/config/file_server.key)
curl -H "Authorization: Bearer ${FILE_KEY}" https://files.{CUSTOM_DOMAIN}/planet -o planet

See SECURITY.md for credential rotation, legacy migration, ztncui ref updates, and public-access guidance.


6. Uninstall

Stop and remove the services:

docker compose down

To remove persisted data as well:

rm -rf ./data/zerotier

Upgrade:

docker compose pull
docker compose up -d

Optional maintenance commands:

./scripts/ztplanet.sh reset-password
./scripts/ztplanet.sh doctor

7. FAQ

Q1: Why cant I ping the target machine?

A: Check firewall rules. On Windows, allow inbound ICMP. Apply equivalent settings on Linux.

Q2: How can I use ZeroTier on iOS?

A: There is a plugin here (requires a jailbroken device): https://github.com/lemon4ex/ZeroTieriOSFix

Q3: Why dont I see the official PLANET peers?

A: This project removes the official roots and uses only your custom PLANET nodes.

Q4: What if my servers IP changes?

A: Redeploy (treat it as a fresh installation).

Q5: PVE LXC container has no network interface?

A: Modify the LXC configuration and uncheck “unprivileged.” The config file is at /etc/pve/lxc/{ID}.conf.

For Proxmox < 7.0, add:

lxc.cgroup.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

For Proxmox ≥ 7.0, add:

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

Q6: Forgot the management password?

A: You can run ./scripts/ztplanet.sh reset-password, or reset it directly in the container. The example below generates a new password, stores it in /app/config/ztncui.initial-password, and applies it immediately:

docker exec ${CONTAINER_NAME:-myztplanet} sh -c 'umask 077; openssl rand -base64 24 | tr -d "\n" > /app/config/ztncui.initial-password; printf "\n" >> /app/config/ztncui.initial-password; ZTNCUI_ADMIN_PASSWORD_FILE=/app/config/ztncui.initial-password node /app/ztncui_admin.js'
docker restart ${CONTAINER_NAME:-myztplanet}
docker exec ${CONTAINER_NAME:-myztplanet} sh -c 'cat /app/config/ztncui.initial-password'

Q7: Cant connect to PLANET?

A: Check firewalls. If youre on Alibaba Cloud, Tencent Cloud, etc., open the required ports in the provider console. Also open them on Linux itself (e.g., ufw).

Q8: How do I know if Im direct or relayed?

A: Run zerotier-cli peers with admin privileges:

<ztaddr>   <ver>  <role> <lat> <link>   <lastTX> <lastRX> <path>
69c0d507d0 -      LEAF      -1 RELAY
93caa675b0 1.12.2 PLANET  -894 DIRECT   4142     4068     110.42.99.46/9994
ab403e2074 1.10.2 LEAF      -1 RELAY

If your peer shows RELAY, traffic is being relayed.

Q9: Why is my ZeroTier throughput unstable?

A: ZeroTier uses UDP. Some regions may apply QoS to UDP. Consider OpenVPN if necessary.

Q10: Do you support custom domains?

A: Not yet.

Q11: Can I deploy on ARM servers?

A: Yes.

Q12: What deployment method do you recommend?

A: Use the repository's compose.yaml directly:

cp .env.example .env
vim .env
docker compose up -d

For temporary lab access over plaintext public HTTP, set HOST_BIND_IP=0.0.0.0 and explicitly load the public override:

docker compose -f compose.yaml -f compose.public-http.yaml up -d

That override sets PUBLIC_HTTP=true inside the container. Production public access should still use a TLS reverse proxy.

Q13: Are upstream versions pinned during builds?

A: Yes. Dockerfile selects the ZeroTier One source with ZEROTIER_REF and pins ztncui with ZTNCUI_REF to the full commit 1b2284864de48d2dcae22582fff122fe24909c3d. The build logs and verifies the actual checked-out commits. GitHub Actions and the local build.sh both pass the ZeroTier build argument explicitly so image tags do not drift away from the source version being built.

New ZeroTier One branches have removed the legacy attic/world directory. This project no longer depends on that tree or on mkworld; it uses the current zerotier-idtool genmoon path with worldType=planet to generate the planet world file directly.

To upgrade ztncui, review the upstream changes first, then update both the default ZTNCUI_REF in Dockerfile and the ZTNCUI_REF in .github/workflows/image-build.yml, and rebuild for verification. The pinned upstream commit does not include package-lock.json or npm-shrinkwrap.json, so the image still runs npm install to resolve npm transitive dependencies; until a reviewed lockfile is added, this remains a known residual reproducibility risk.


8. Roadmap

🥰 Your support accelerates development 🥰

  • MultiPLANET support
  • Customizable port 3443
  • Split deployment of PLANET and controller

9. Risk Statement

This project is for learning and research only. Commercial use is not encouraged. We are not liable for any loss incurred from using this project.



11. Donations & Support

If this project helps you, consider supporting development:

Donate

12. Acknowledgments

Thanks to the following supporters—your encouragement keeps this project going.

In chronological order:

  • 随性
  • 你好
  • Calvin
  • 小猪猪的饲养员
  • 情若犹在
  • 天天星期天
  • 啊乐
  • 夏末秋至
  • **忠
  • 岸芷汀兰
  • Kimi Chen
  • 匿名
  • 阳光报告旷课
  • 濂溪先生
  • Water
  • 匿名
  • 匿名
  • 精钢葫芦娃
  • 王小新
  • 匿名
  • Duck不必

📚 References