优化部署脚本,增强错误处理和用户提示,更新 README 文档以反映最新的使用说明

This commit is contained in:
2026-02-22 23:42:05 +08:00
parent 5afe54e6eb
commit 9a35e69c82
2 changed files with 114 additions and 40 deletions

View File

@@ -9,28 +9,47 @@
└── zt-mkworld planet 生成目录(暂未使用)
## 快速部署
1. 上传 zerotier-aio-zh.tar/opt/zerotier-aio/
2. chmod +x deploy-zerotier-aio.sh
3. sudo ./deploy-zerotier-aio.sh
4. 阿里云安全组放行9993/udp、3000/tcp、3443/tcp
1. `deploy-zerotier-aio.sh``zerotier-aio-zh.tar` 放到 `/opt/zerotier-aio/`
2. 执行:
```bash
cd /opt/zerotier-aio
chmod +x deploy-zerotier-aio.sh
sudo ./deploy-zerotier-aio.sh
```
3. 阿里云安全组放行:`9993/udp`、`3000/tcp`、`3443/tcp`
说明:
- 本脚本按阿里云环境优化,会优先从 `http://100.100.100.200/latest/meta-data/eipv4` 获取公网 IP。
- 这是离线部署脚本,`zerotier-aio-zh.tar` 必须存在;不会依赖 Docker Hub 拉镜像。
## 备份与迁移
备份:
tar -czf zerotier-aio-$(date +%Y%m%d).tar.gz /opt/zerotier-aio
```bash
tar -czf zerotier-aio-backup-$(date +%Y%m%d).tar.gz /opt/zerotier-aio
```
新服务器恢复:
1. 解压到 /opt/zerotier-aio
2. 修改 docker-compose.yml 中的 MYADDR 为新公网 IP
3. 如果 Moon IP 变了,需要重新生成 Moon(删除 zerotier-one/moons.d 后重新运行脚本)
4. docker load -i zerotier-aio-zh.tar
5. docker compose up -d
1. 将备份包、`deploy-zerotier-aio.sh`、`zerotier-aio-zh.tar` 放到新服务器 `/opt/zerotier-aio/`
2. 运行脚本,脚本会自动恢复并按当前公网 IP 重写 `docker-compose.yml`
3. 如果是迁移且公网 IP 已变化,需要重新生成 Moon
```bash
FORCE_REGEN_MOON=1 sudo ./deploy-zerotier-aio.sh
```
## 客户端加入
1. 手动放置 Moon 文件 或 执行:
```bash
zerotier-cli orbit <MoonID> <MoonID>
2. zerotier-cli join <网络ID>
```
2. 执行:
```bash
zerotier-cli join <网络ID>
```
3. Web 面板授权成员
4. set <网络ID> allowManaged=1
4. 按需开启托管路由:
```bash
zerotier-cli set <网络ID> allowManaged=1
```
## 注意事项
- 密码admin123首次登录立即修改

View File

@@ -1,5 +1,5 @@
#!/bin/bash
set -e
set -Eeuo pipefail
echo "======================================"
echo " ZeroTier AIO 离线快速部署脚本 v2"
@@ -8,47 +8,84 @@ echo "======================================"
[ "$EUID" -ne 0 ] && { echo "请用 root 执行"; exit 1; }
# 安装依赖
command -v docker &>/dev/null || {
INSTALL_DIR="/opt/zerotier-aio"
IMAGE_TAR="$INSTALL_DIR/zerotier-aio-zh.tar"
IMAGE_REF="niliaerith/zerotier-aio-zh:latest"
CONTAINER_NAME="zerotier-aio"
FORCE_REGEN_MOON="${FORCE_REGEN_MOON:-0}"
if ! command -v apt >/dev/null 2>&1; then
echo "当前脚本仅支持 Debian/Ubuntu需要 apt"
exit 1
fi
# 安装依赖(离线环境至少要有 docker + compose + curl + ip
if ! command -v docker >/dev/null 2>&1; then
apt update -y
apt install -y docker.io docker-compose-plugin curl
apt install -y docker.io docker-compose-plugin curl iproute2
systemctl enable --now docker
}
fi
if ! docker compose version >/dev/null 2>&1; then
apt update -y
apt install -y docker-compose-plugin
fi
command -v curl >/dev/null 2>&1 || apt install -y curl
command -v ip >/dev/null 2>&1 || apt install -y iproute2
# 检查 TUN
modprobe tun 2>/dev/null || true
[ -c /dev/net/tun ] || { echo "TUN 不可用"; exit 1; }
# 获取公网 IP
PUBLIC_IP=$(curl -s http://100.100.100.200/latest/meta-data/eipv4 || true)
[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -n1)
[ -z "$PUBLIC_IP" ] && read -p "无法自动获取公网IP请手动输入: " PUBLIC_IP
PUBLIC_IP=$(curl -fsS --connect-timeout 2 --max-time 5 http://100.100.100.200/latest/meta-data/eipv4 || true)
[ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(ip route get 1.1.1.1 2>/dev/null | awk '/src/ {for(i=1;i<=NF;i++) if($i=="src"){print $(i+1); exit}}')
[ -z "$PUBLIC_IP" ] && read -r -p "无法自动获取公网IP请手动输入: " PUBLIC_IP
[ -n "$PUBLIC_IP" ] || { echo "未获取到公网 IP退出"; exit 1; }
echo "公网 IP: $PUBLIC_IP"
INSTALL_DIR="/opt/zerotier-aio"
mkdir -p "$INSTALL_DIR"
cd "$INSTALL_DIR"
# 如果有备份包,优先恢复
if ls zerotier-aio-backup*.tar.gz 1>/dev/null 2>&1; then
echo "检测到备份包,正在恢复..."
tar -xzf zerotier-aio-backup*.tar.gz -C /opt
BACKUP_FILE=$(ls -t zerotier-aio-backup*.tar.gz | head -n1)
echo "检测到备份包,正在恢复: $BACKUP_FILE"
tar -xzf "$BACKUP_FILE" -C /opt
elif ls zerotier-aio-essential*.tar.gz 1>/dev/null 2>&1; then
tar -xzf zerotier-aio-essential*.tar.gz -C /opt
BACKUP_FILE=$(ls -t zerotier-aio-essential*.tar.gz | head -n1)
echo "检测到 essential 包,正在恢复: $BACKUP_FILE"
tar -xzf "$BACKUP_FILE" -C /opt
elif ls zerotier-aio-[0-9]*.tar.gz 1>/dev/null 2>&1; then
# 兼容旧版文档中的备份命名
BACKUP_FILE=$(ls -t zerotier-aio-[0-9]*.tar.gz | head -n1)
echo "检测到旧版命名备份,正在恢复: $BACKUP_FILE"
tar -xzf "$BACKUP_FILE" -C /opt
fi
# 加载镜像(如果 tar 存在
[ -f zerotier-aio-zh.tar ] && {
echo "加载本地镜像..."
docker load -i zerotier-aio-zh.tar
# 加载镜像(离线强依赖
[ -f "$IMAGE_TAR" ] || {
echo "未找到离线镜像包: $IMAGE_TAR"
echo "请先上传 zerotier-aio-zh.tar$INSTALL_DIR"
exit 1
}
echo "加载本地镜像..."
docker load -i "$IMAGE_TAR"
docker image inspect "$IMAGE_REF" >/dev/null 2>&1 || {
echo "镜像加载后未找到: $IMAGE_REF"
echo "请确认 tar 内镜像标签与 docker-compose.yml 一致"
exit 1
}
# 生成或使用 docker-compose.yml
cat > docker-compose.yml <<EOF
services:
zerotier-aio:
image: niliaerith/zerotier-aio-zh:latest
container_name: zerotier-aio
image: $IMAGE_REF
pull_policy: never
container_name: $CONTAINER_NAME
restart: unless-stopped
cap_add: [ALL]
devices: [/dev/net/tun]
@@ -70,27 +107,45 @@ EOF
# 启动
docker compose up -d
sleep 15
echo "等待容器初始化..."
for _ in $(seq 1 30); do
if docker exec "$CONTAINER_NAME" test -f /var/lib/zerotier-one/identity.public >/dev/null 2>&1; then
break
fi
sleep 1
done
docker exec "$CONTAINER_NAME" test -f /var/lib/zerotier-one/identity.public >/dev/null 2>&1 || {
echo "容器未完成初始化,未找到 identity.public"
exit 1
}
# 检查 Moon如果 moons.d 为空则生成)
MOONS_DIR="./zerotier-one/moons.d"
if [ ! -d "$MOONS_DIR" ] || [ -z "$(ls -A "$MOONS_DIR")" ]; then
if [ "$FORCE_REGEN_MOON" = "1" ]; then
rm -f "$MOONS_DIR"/*.moon 2>/dev/null || true
fi
if [ ! -d "$MOONS_DIR" ] || [ -z "$(find "$MOONS_DIR" -maxdepth 1 -name '*.moon' -print -quit 2>/dev/null)" ]; then
echo "生成 Moon..."
docker exec zerotier-aio zerotier-idtool initmoon /var/lib/zerotier-one/identity.public > /tmp/moon.json
sed -i "s|\"stableEndpoints\": \[\]|\"stableEndpoints\": [\"$PUBLIC_IP/9993\"]|" /tmp/moon.json
docker exec zerotier-aio bash -c "cd /tmp && zerotier-idtool genmoon moon.json"
MOON_FILE=$(docker exec zerotier-aio find /tmp -name "*.moon" | head -n1)
docker exec "$CONTAINER_NAME" sh -c "zerotier-idtool initmoon /var/lib/zerotier-one/identity.public > /tmp/moon.json"
docker exec "$CONTAINER_NAME" sh -c "sed -i 's|\"stableEndpoints\": \\[\\]|\"stableEndpoints\": [\"$PUBLIC_IP/9993\"]|' /tmp/moon.json"
docker exec "$CONTAINER_NAME" sh -c "cd /tmp && zerotier-idtool genmoon moon.json"
MOON_FILE=$(docker exec "$CONTAINER_NAME" sh -c "find /tmp -maxdepth 1 -name '*.moon' | head -n1")
[ -n "$MOON_FILE" ] || { echo "Moon 生成失败"; exit 1; }
mkdir -p "$MOONS_DIR"
docker cp "zerotier-aio:$MOON_FILE" "$MOONS_DIR/"
docker cp "$CONTAINER_NAME:$MOON_FILE" "$MOONS_DIR/"
MOON_ID=$(basename "$MOON_FILE" .moon)
docker restart zerotier-aio
docker restart "$CONTAINER_NAME" >/dev/null
else
MOON_ID=$(ls "$MOONS_DIR"/*.moon | head -n1 | xargs basename | cut -d. -f1)
MOON_ID=$(find "$MOONS_DIR" -maxdepth 1 -name '*.moon' | head -n1 | xargs basename | cut -d. -f1)
fi
# 防火墙ufw
command -v ufw &>/dev/null && {
ufw allow 9993/udp 3000/tcp 3443/tcp
ufw allow 9993/udp || true
ufw allow 3000/tcp || true
ufw allow 3443/tcp || true
ufw reload || true
}