背景回顾
前几年,基于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
本文永久链接:https://liuzhicong.cn/index.php/guide/78.html
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
如有版权疑问交流,请给我留言:oneisall8955@gmail.com
本文永久链接:https://liuzhicong.cn/index.php/guide/78.html
博主,我有一个问题就是家里是动态公网IPv4,按照之前的来说是要一个固定的公网IP的,现在这个ZTNET搭建出来有没有要求就是固定公网IPv4呀?
zerotier的planet需要固定公网IP。
ddns可以考虑n2n。
如果不是p2p方式,也可以考虑softether。
对了wireguard也支持ddns
我配置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服务器。
以上是我的疑问,恳请博主不吝赐教。
第一个问也是我使用过程中遇到的问题。
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