ZeroTier自建Planet服务器 IP 变更后,完整恢复旧网络和成员数据
当自建 ZeroTier Planet 服务的服务器公网 IP 发生变更时,如果直接重新运行 deploy.sh 或 docker compose up,会生成全新的控制器身份和 planet 文件,导致旧客户端无法连接,所有历史网络、成员授权记录全部丢失。
本文提供一套精准恢复方案 ,核心目标是:
保留原有控制器 root identity
保留所有旧虚拟网络(Network ID)
保留成员授权和 IP 分配
仅将 planet / moon 文件中的公网 endpoint 更新为新 IP
最终效果:客户端只需替换一次 planet 文件即可无缝接入,所有历史数据完整保留。
准备工作
新安装目录示例:/root/docker-zerotier-planet/data/zerotier
旧备份目录示例:/root/docker-zerotier-planet/data/backup/zerotier(建议提前完整备份)
必须恢复的关键旧数据
以下文件决定了控制器身份、网络 ID 和成员授权记录,必须从备份中恢复:
data/backup/zerotier/one/identity.secret
data/backup/zerotier/one/identity.public
data/backup/zerotier/one/authtoken.secret
data/backup/zerotier/one/current.c25519
data/backup/zerotier/one/previous.c25519
data/backup/zerotier/one/moon.json
data/backup/zerotier/one/controller.d/(存放所有网络和成员信息)
不建议直接恢复 的旧生成物(会包含旧 IP):
planet、*.moon 文件
peers.d/、moons.d/ 等运行时目录
恢复步骤
1. 停止容器并备份当前状态
1 2 3 4 5 cd /root/docker-zerotier-planetdocker rm -f myztplanet zip -qr data/zerotier_before_restore.zip data/zerotier
2. 恢复旧控制器身份和网络数据
Bash
1 2 3 4 5 6 7 8 9 10 11 12 # 删除可能冲突的 controller.d rm -rf data/zerotier/one/controller.d # 恢复关键文件 cp -a data/backup/zerotier/one/controller.d data/zerotier/one/ cp -a data/backup/zerotier/one/identity.secret data/zerotier/one/ cp -a data/backup/zerotier/one/identity.public data/zerotier/one/ cp -a data/backup/zerotier/one/authtoken.secret data/zerotier/one/ cp -a data/backup/zerotier/one/current.c25519 data/zerotier/one/ cp -a data/backup/zerotier/one/previous.c25519 data/zerotier/one/ cp -a data/backup/zerotier/one/moon.json data/zerotier/one/ cp -a data/backup/zerotier/one/mkworld data/zerotier/one/
3. 补齐容器所需的工具软链接
Bash
1 2 3 ln -sfn ../../../usr/sbin/zerotier-one data/zerotier/one/zerotier-one ln -sfn ../../../usr/sbin/zerotier-one data/zerotier/one/zerotier-cli ln -sfn ../../../usr/sbin/zerotier-one data/zerotier/one/zerotier-idtool
4. 清理旧运行状态和旧生成物
Bash
1 2 3 4 5 6 7 8 9 rm -rf data/zerotier/one/peers.d data/zerotier/one/moons.d mkdir -p data/zerotier/one/peers.d data/zerotier/one/moons.d rm -f data/zerotier/one/*.moon \ data/zerotier/dist/*.moon \ data/zerotier/dist/planet \ data/zerotier/one/planet \ data/zerotier/one/world.bin \ data/zerotier/one/zerotier-one.pid
5. 使用新 IP 重新生成 planet 和 moon
Bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 cd /root/docker-zerotier-planet NEW_IP=$(tr -d '\r\n' < data/zerotier/config/ip_addr4) IMG=xubiaolin/zerotier-planet:latest docker run --rm --entrypoint sh \ -e NEW_IP="$NEW_IP" \ -v /root/docker-zerotier-planet/data/zerotier/dist:/app/dist \ -v /root/docker-zerotier-planet/data/zerotier/one:/var/lib/zerotier-one \ -v /root/docker-zerotier-planet/data/zerotier/config:/app/config \ "$IMG" -lc ' set -e ln -sf /usr/sbin/zerotier-one /tmp/zerotier-idtool cd /var/lib/zerotier-one ZT_PORT=$(cat /app/config/zerotier-one.port | tr -d "\r") [ -s moon.json ] || /tmp/zerotier-idtool initmoon identity.public > moon.json jq --argjson eps "[\"$$ {NEW_IP}/ $${ZT_PORT}\"]" \ ".roots[0].stableEndpoints = \$eps" \ moon.json > moon.json.tmp mv moon.json.tmp moon.json rm -f ./*.moon moons.d/*.moon /app/dist/*.moon /app/dist/planet world.bin planet /tmp/zerotier-idtool genmoon moon.json mkdir -p moons.d cp ./*.moon moons.d/ ./mkworld cp world.bin /app/dist/planet cp world.bin /var/lib/zerotier-one/planet cp ./*.moon /app/dist/ echo "新 endpoint:" jq -c ".roots[0].stableEndpoints" moon.json sha256sum /app/dist/planet /var/lib/zerotier-one/planet '
重要 :data/zerotier/dist/planet 和 data/zerotier/one/planet 两个文件必须完全一致。
6. 修复 ztncui Token(避免 401 错误)
Bash
1 2 TOKEN=$(cat data/zerotier/one/authtoken.secret | tr -d '\r\n') sed -i "s/^ZT_TOKEN=.*/ZT_TOKEN=${TOKEN}/" data/zerotier/ztncui/src/.env
7. 启动容器
Bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 cd /root/docker-zerotier-planet ZT_PORT=$(tr -d '\r\n' < data/zerotier/config/zerotier-one.port) API_PORT=$(tr -d '\r\n' < data/zerotier/config/ztncui.port) FILE_PORT=$(tr -d '\r\n' < data/zerotier/config/file_server.port) IPV4=$(tr -d '\r\n' < data/zerotier/config/ip_addr4) IPV6=$(tr -d '\r\n' < data/zerotier/config/ip_addr6) docker run -d \ --name myztplanet \ -p $$ {ZT_PORT}: $${ZT_PORT} \ -p $$ {ZT_PORT}: $${ZT_PORT}/udp \ -p $$ {API_PORT}: $${API_PORT} \ -p $$ {FILE_PORT}: $${FILE_PORT} \ -e IP_ADDR4=${IPV4} \ -e IP_ADDR6=${IPV6} \ -e ZT_PORT=${ZT_PORT} \ -e API_PORT=${API_PORT} \ -e FILE_SERVER_PORT=${FILE_PORT} \ -v /root/docker-zerotier-planet/data/zerotier/dist:/app/dist \ -v /root/docker-zerotier-planet/data/zerotier/ztncui:/app/ztncui \ -v /root/docker-zerotier-planet/data/zerotier/one:/var/lib/zerotier-one \ -v /root/docker-zerotier-planet/data/zerotier/config:/app/config \ --restart unless-stopped \ xubiaolin/zerotier-planet:latest
服务端验证
Bash
1 2 3 4 5 6 7 8 9 10 11 # 确认 root ID 是否为旧值 cut -d: -f1 data/zerotier/one/identity.public # 确认 endpoint 已更新 jq -r '.roots[0].stableEndpoints[]' data/zerotier/one/moon.json # 查询控制器网络列表(应显示所有旧 Network ID) docker exec myztplanet sh -lc ' TOKEN=$(cat /var/lib/zerotier-one/authtoken.secret) wget -qO- --header="X-ZT1-Auth: $TOKEN" http://127.0.0.1:9994/controller/network '
客户端操作
planet 下载地址 :http://新IP :文件服务器端口/planet?key=xxx
moon 下载地址 (可选):http://新IP :文件服务器端口/0000000651177f3e.moon?key=xxx
Linux 客户端示例:
Bash
1 2 3 4 5 6 systemctl stop zerotier-one cp planet /var/lib/zerotier-one/planet systemctl start zerotier-one zerotier-cli peers zerotier-cli listnetworks
正常情况下会显示 PLANET … DIRECT … 新IP/9994。
常见问题与注意事项
ztncui 面板打不开 :检查 .env 中的 ZT_TOKEN 是否已同步更新。
客户端仍显示旧 IP :确认 planet 文件 MD5 一致,且已重启客户端服务。
UDP 连不通 :检查防火墙、安全组、运营商 NAT 是否放行 9994/udp 端口。
下次 IP 变更建议 :提前准备自动化恢复脚本,或考虑使用域名 + DDNS 方案减少 planet 硬编码问题。