MENU

ZTNET 搭建 zerotier planet 私有根教程

October 28, 2024 • Read: 2148 • 教程・折腾

背景回顾展开目录

前几年,基于 zerotier+ztncui 搭建了私有 planet。开源的 ztncui 客户端比较简陋,核心功能齐全,有些小 bug,当时没有别的更好的可以选择(zero-ui 也很简陋),将就用着,反正也是初始化网络,调整路由,新设备接入才打开后台使用。
这里先回顾下过往历程:

  • 21 年在 v2 上摸鱼看到这个贴子五分钟自建 ZeroTier 的 Planet/Controller,第一次知道 zerotier 可以自建,相关概念很模糊,帖子介绍的是搭建 controller,并非真实的私有根。后续找了搭建 planet+controller 的教程跟着搭建起来 zerotier 的 planet 服务器(根服务器)的搭建踩坑记。无需 zerotier 官网账号 那时候搭建需要手动修改 mkworld.cpp 源码,填写自己的 ip,编译 cpp 才有 world.bin(就是 planet),服务端用 systemd 管理。
  • 22 年服务器到期,需要迁移,把 90% 以上的服务 docker 容器化。于是基于 docker 重新搭建了一套 docker-zerotier-planet,原理和第一次搭建是一样的,这次新增了下载 planet 接口 api,不需要手动编译,不过客户端还是 ztncui。
  • 2024 年 4 月无意间发现,有另外一个很美观功能完善的开源客户端: ztnet GitHub 地址。简直是太符合我的胃口了,除了存储使用 postgres,会占用多一点内存,如果能优化为 sqlite3 就完美了。

ZTNET 官方 docker-compose展开目录

官方 docker-compose 文档:https://ztnet.network/installation/docker-compose

  • services:
  • postgres:
  • image: postgres:15.2-alpine
  • container_name: postgres
  • restart: unless-stopped
  • environment:
  • POSTGRES_USER: postgres
  • POSTGRES_PASSWORD: postgres
  • POSTGRES_DB: ztnet
  • volumes:
  • - postgres-data:/var/lib/postgresql/data
  • networks:
  • - app-network
  • zerotier:
  • image: zyclonite/zerotier:1.14.0
  • hostname: zerotier
  • container_name: zerotier
  • restart: unless-stopped
  • volumes:
  • - zerotier:/var/lib/zerotier-one
  • cap_add:
  • - NET_ADMIN
  • - SYS_ADMIN
  • devices:
  • - /dev/net/tun:/dev/net/tun
  • networks:
  • - app-network
  • ports:
  • - "9993:9993/udp"
  • environment:
  • - ZT_OVERRIDE_LOCAL_CONF=true
  • - ZT_ALLOW_MANAGEMENT_FROM=172.31.255.0/29
  • ztnet:
  • image: sinamics/ztnet:latest
  • container_name: ztnet
  • working_dir: /app
  • volumes:
  • - zerotier:/var/lib/zerotier-one
  • restart: unless-stopped
  • ports:
  • - 3000:3000
  • # - 127.0.0.1:3000:3000 <--- Use / Uncomment this line to restrict access to localhost only
  • environment:
  • POSTGRES_HOST: postgres
  • POSTGRES_PORT: 5432
  • POSTGRES_USER: postgres
  • POSTGRES_PASSWORD: postgres
  • POSTGRES_DB: ztnet
  • NEXTAUTH_URL: "http://localhost:3000" # !! Important !! Set the NEXTAUTH_URL environment variable to the canonical URL or IP of your site with port 3000
  • NEXTAUTH_SECRET: "random_secret"
  • NEXTAUTH_URL_INTERNAL: "http://ztnet:3000" # Internal NextAuth URL for 'ztnet' container on port 3000. Do not change unless modifying container name.
  • networks:
  • - app-network
  • links:
  • - postgres
  • depends_on:
  • - postgres
  • - zerotier
  • ############################################################################
  • # #
  • # Uncomment the section below to enable HTTPS reverse proxy with Caddy. #
  • # #
  • # Steps: #
  • # 1. Replace <YOUR-PUBLIC-HOST-NAME> with your actual public domain name. #
  • # 2. Uncomment the caddy_data volume definition in the volumes section. #
  • # #
  • ############################################################################
  • # https-proxy:
  • # image: caddy:latest
  • # container_name: ztnet-https-proxy
  • # restart: unless-stopped
  • # depends_on:
  • # - ztnet
  • # command: caddy reverse-proxy --from <YOUR-PUBLIC-HOST-NAME> --to ztnet:3000
  • # volumes:
  • # - caddy_data:/data
  • # networks:
  • # - app-network
  • # links:
  • # - ztnet
  • # ports:
  • # - "80:80"
  • # - "443:443"
  • volumes:
  • zerotier:
  • postgres-data:
  • # caddy_data:
  • networks:
  • app-network:
  • driver: bridge
  • ipam:
  • driver: default
  • config:
  • - subnet: 172.31.255.0/29

官方 docker-compose 解释展开目录

使用了 3 个组件

  • postgres: 存储持久层,端口 5432 千万不要映射到公网
  • zerotier: 作为 controller+planet,提供 api 给 ztnet,需要暴露 9993 UDP 端口
  • ztnet: 类似 ztncui,作为控制器的前端,端口为 3000

优化搭建过程展开目录

基于官方的思路,可以很简单的自定义自己的运行场景。这里做出几点优化:

  • 由于 postgres 是数据库基础组件,可以单独出来。如果已经存在,就不需要搭建;如果新搭建,后续其他服务也可以复用。
  • 数据持久化,使用目录映射方式而非 docker volumes,便于后续备份,存储的目录均为 /opt/software/xxx 下。
  • docker 网络先默认提前设置好,而非在 docker-compose 中定义。
  • 反向代理使用 nginx,nginx 如果是容器化,也提前加入同一个网络,这样不需要暴露 3000 端口

docker 创建网络及存储目录展开目录

网络名称:docker_app_default
子网访问:10.254.1.0/24

  • docker network create docker_app_default --driver=bridge --subnet=10.254.1.0/24
  • mkdir -p /opt/software/postgres/data
  • mkdir -p /opt/software/zerotier/data

postgres展开目录

  • postgres 的 docker-compose 文件
  • services:
  • postgres:
  • image: postgres:15.2-alpine
  • container_name: postgres
  • restart: unless-stopped
  • environment:
  • - TZ=Asia/Shanghai
  • - POSTGRES_PASSWORD=POSTGRES
  • - POSTGRES_USER=POSTGRES
  • volumes:
  • - /opt/software/postgres/data:/var/lib/postgresql/data
  • networks:
  • default:
  • name: docker_app_default
  • external: true
  • 创建 zenet 数据库
  • docker exec -it postgres psql -U POSTGRES -c "\l" # 查看数据库列表
  • docker exec -it postgres psql -U POSTGRES -c "CREATE DATABASE ztnet" # 创建数据库
  • docker exec -it postgres psql -U POSTGRES -c "\l" # 再次查看数据库列表

当然,为了安全性,可以为数据库创建专门的用户及密码,这里不做展开。

zerotier+ztnet展开目录

  • services:
  • zerotier:
  • image: zyclonite/zerotier:1.14.0
  • hostname: zerotier
  • container_name: zerotier
  • restart: unless-stopped
  • volumes:
  • - /opt/software/zerotier/data:/var/lib/zerotier-one
  • cap_add:
  • - NET_ADMIN
  • - SYS_ADMIN
  • devices:
  • - /dev/net/tun:/dev/net/tun
  • ports:
  • - "9993:9993" # 暴露多一个tcp,其实可以删掉
  • - "9993:9993/udp"
  • environment:
  • - ZT_OVERRIDE_LOCAL_CONF=true
  • - ZT_ALLOW_MANAGEMENT_FROM=0.0.0.0/0 # 限制管理controller的子网,为了更安全可以填写上面创建的 10.254.1.0/24
  • ztnet:
  • image: sinamics/ztnet:latest
  • container_name: ztnet
  • working_dir: /app
  • volumes:
  • - /opt/software/zerotier/data:/var/lib/zerotier-one
  • restart: unless-stopped
  • ports:
  • - 3000:3000 # 可选,不经过反向代理,直接暴露3000端口来访问,需要打开端口映射,同时开放主机防火墙和安全策略组
  • environment:
  • POSTGRES_HOST: postgres
  • POSTGRES_PORT: 5432
  • POSTGRES_USER: POSTGRES
  • POSTGRES_PASSWORD: POSTGRES
  • POSTGRES_DB: ztnet
  • NEXTAUTH_URL: "https://ztnet.example.com" # 这里填写外网控制,如果经过反向代理,则填写域名,如果没有,则填写http://ip:3000
  • NEXTAUTH_SECRET: "random_secret"
  • NEXTAUTH_URL_INTERNAL: "http://ztnet:3000"
  • networks:
  • default:
  • name: docker_app_default
  • external: true

nginx 反向代理展开目录

  • 直接 http 访问 nginx,nginx 加入 ztnet 同一个网络(例如 cloudflare 小云朵,自动 ssl)
  • server {
  • listen 80;
  • listen [::]:80;
  • server_name ztnet.example.com;
  • client_max_body_size 20m;
  • charset utf-8;
  • resolver 127.0.0.11 valid=30s;
  • set $backend "ztnet:3000";
  • location / {
  • proxy_pass http://$backend;
  • proxy_set_header Host $host;
  • proxy_set_header X-Real-IP $remote_addr;
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • proxy_set_header X-Forwarded-Proto $scheme;
  • proxy_set_header X-Forwarded-Protocol $scheme;
  • proxy_set_header X-Forwarded-Host $http_host;
  • proxy_set_header REMOTE-HOST $remote_addr;
  • proxy_set_header Upgrade $http_upgrade;
  • proxy_set_header Connection $connection_upgrade;
  • proxy_set_header Range $http_range;
  • proxy_set_header If-Range $http_if_range;
  • client_max_body_size 20m;
  • proxy_cache off;
  • proxy_buffering off;
  • proxy_http_version 1.1;
  • }
  • }
  • 本机 nginx 接管 ssl,并且 nginx 没有加入 ztnet 同一个网络
  • server {
  • listen 80;
  • listen [::]:80;
  • server_name ztnet.example.com;
  • # 将 HTTP 请求重定向至 HTTPS
  • return 301 https://$host$request_uri;
  • }
  • server {
  • listen 443 ssl;
  • listen [::]:443 ssl;
  • http2 on;
  • server_name ztnet.example.com;
  • # include /opt/software/nginx/conf.d/example.com.ssl.conf.incl;
  • ssl_certificate /opt/software/nginx/ssl.d/example.com/cert.pem;
  • ssl_certificate_key /opt/software/nginx/ssl.d/example.com/key.pem;
  • ssl_session_timeout 1d;
  • ssl_session_cache shared:SSL:50m;
  • ssl_session_tickets off;
  • ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
  • ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;
  • ssl_prefer_server_ciphers on;
  • add_header Strict-Transport-Security max-age=15768000;
  • ssl_stapling on;
  • access_log /opt/software/nginx/logs/ztnet.access.log;
  • error_log /opt/software/nginx/logs/ztnet.error.log;
  • location / {
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • proxy_set_header Host $http_host;
  • proxy_set_header X-Real-IP $remote_addr;
  • proxy_set_header Range $http_range;
  • proxy_set_header If-Range $http_if_range;
  • proxy_redirect off;
  • proxy_pass http://127.0.0.1:3000;
  • }
  • }

使用展开目录

搭建好后,打开 ztnet.example.com 或 http://ip:3000 注册第一个用户为管理账号。
私有根的使用,详见官网 https://ztnet.network/usage/private_root


本文由 ONE 创作,采用 知识共享署名 4.0 国际许可协议进行许可
本站文章除注明转载 / 出处外,均为本站原创或翻译,转载前请务必署名
如有版权疑问交流,请给我留言:oneisall8955@gmail.com
本文永久链接:http://liuzhicong.cn/index.php/guide/78.html

Last Modified: October 30, 2024
Archives QR Code Tip
QR Code for this page
Tipping QR Code
Leave a Comment

4 Comments
  1. 2sdk 2sdk

    博主,我有一个问题就是家里是动态公网 IPv4,按照之前的来说是要一个固定的公网 IP 的,现在这个 ZTNET 搭建出来有没有要求就是固定公网 IPv4 呀?

    1. @2sdkzerotier 的 planet 需要固定公网 IP。

      ddns 可以考虑 n2n。
      如果不是 p2p 方式,也可以考虑 softether。
      对了 wireguard 也支持 ddns

  2. 心空之上 心空之上

    我配置 zerotier 私有根服务器的历程跟博主差不多,也是一开始自己编译源码创建私有 planet,最近要将服务都 docker 化,所以寻找 zerotier 私有根服务器的 docker 搭建方法,也是先找到 docker-zerotier-planet,然后再看到了博主的教程,最后打算用 ztnet 部署私有根服务器了。
    在配置过程有几个疑问,想请教一下楼主:
    1. 按照 ztnet 官方的 docker compose,容器使用的网络都是桥接模式,controller 的作用应该只是提供管理网络的界面和下载私有 planet 的作用,如果我要将部署私有根服务器的机器加入 zt 网络,是不是得在宿主机上安装 zerotier 或者再用一个 host 网络模式的 zerotier 进行加入?目前我的方案是将 ztnet 官方 compose file 中的 zerotier 容器配置改为 host 模式,这样加入 zt 网络就可以在宿主机中使用了。
    2.ztnet 有配置私有 moon 服务器的功能吗?如果我将一台服务器设置为私有 planet 服务器,有必要再将这台服务器再配置成私有 moon 服务器吗?因为 docker-zerotier-planet 默认会生成 planet 和 moon 的配置,所以不知道有没有必要再配置 moon 服务器。
    以上是我的疑问,恳请博主不吝赐教。

    1. @心空之上第一个问也是我使用过程中遇到的问题。

      ztnet 已经搭建了一段时间,后来才遇到宿主机访问到家里的设备需求。

      我用了个比较笨的方式(对 Linux/docker 网络研究不是很深入,似懂非懂的状态,不想改动已经搭建好的环境)

      我在宿主机用 apt/yum 安装了一个 zerotier,替换 planet,肯定会遇到端口冲突,修改 local.conf 文件,修改 settings.primaryPort 为非 9993,重新跑起来。并且修改云主机安全组暴露这个端口。

      这种方式就像你说的那样,重新运行了一个 zerotier 实例当做客户端加入网络,内存占用会有点浪费,并且不是容器化,有点不够优雅。

      如果用 host 模式运行,宿主机的网络没问题,这是个更好的办法。

      另外,更多属于个人使用习惯问题,我尽量不用 host 方式来运行容器,host 用宿主机的网络接口,等于没有隔离性(虽然 host 方式性能更好)

      第二个问题,我认为没必要再用 moon 了,替换为 planet 就行。

      但我看到 up 主韩风说 moon 才是 zerotier 的私有根正确玩法,即使官方文档推荐 moon,我很难认同这种说法。制作私有 planet 当然会打破 zerotier 官方自带的 planet 给我们的健壮性。但我们就是因为官方 planet 延迟太大不够稳定我们才自建。

      如果你后面调研探讨到 moon 是有必要的,可以反馈交流(精力时间有限,查看文档搜索太花时间了)

      ztnet 有计划在生成 moon:详细看 issue:
      https://github.com/sinamics/ztnet/issues/309