🚀 运行: ...
IP: ...
ISP: 检测中...

纯 IPv6 Alpine 小鸡 Docker 部署哪吒面板 v0(nezha-zero)+ Cloudflare Tunnel

为什么写这篇

手里有一台 Scaleway Stardust 小鸡:纯 IPv6、Alpine 系统、硬盘只有 3G。想在上面跑个哪吒面板 v0(railzen/nezha-zero,本文用 v0.20.28),全程实测通过,整理成完整步骤,照着做就能复现。

方案定为:

  • Docker Compose 跑两个容器:nezha-dashboard 主控 + cloudflared 隧道
  • Web 访问走 Cloudflare Tunnel,不用 nginx,不占 80/443
  • Agent 上报走机器公网 IPv6 直连 5555 端口
  • 两个容器都用 network_mode: host,省掉折腾 Docker IPv6 NAT 的麻烦
浏览器 ──HTTPS──▶ Cloudflare 边缘 ──隧道──▶ cloudflared ──HTTP──▶ localhost:8008(dashboard)
被控机 ──直连──▶ 小鸡公网 IPv6 : 5555(gRPC 上报)

前提

  • 一台纯 IPv6 的 Alpine 小鸡,有 root 权限(本文在 Scaleway Stardust、3G 硬盘上实测)
  • 一个已托管在 Cloudflare 的域名(本文用 panel.example.com 占位,请换成你自己的)
  • 架构确认:uname -m 看是 x86_64 还是 aarch64,下面下载对应版本

步骤一:装 WARP,拿到 IPv4 出站

纯 IPv6 机器上,GitHub 和 Docker Hub 都是纯 IPv4,没有 IPv4 出站后面下载和拉镜像全部失败。所以第一步先装 WARP。

apk add wireguard-tools
# 下载 wgcf(amd64 示例,arm64 请去 releases 页换对应包)
wget -4 https://github.com/ViRb3/wgcf/releases/download/v2.2.22/wgcf_2.2.22_linux_amd64 -O /usr/local/bin/wgcf
chmod +x /usr/local/bin/wgcf

# 注册并生成配置,按提示一路回车
wgcf register --accept-tos
wgcf generate

mkdir -p /etc/wireguard
cp wgcf-profile.conf /etc/wireguard/warp.conf

# OpenRC 启动并设开机自启
rc-update add wg-quick.warp default
rc-service wg-quick.warp start

# 验证 IPv4 出站通了(能返回一个 IPv4 地址即成功)
curl -4 -s https://api.ipify.org; echo

注意:WARP 只解决出站(本机去下载东西、拉镜像)。Agent 入站还是走本机公网 IPv6,纯 IPv4 的小鸡连不上这个面板。

步骤二:装 Docker

apk update
apk add docker docker-compose
rc-update add docker default
service docker start
docker -v
docker-compose -v

步骤三:下载 dashboard 二进制

nezha-zero 官方没有现成的生产镜像(仓库自带的 compose 是开发配置),所以用官方 release 的二进制自己打镜像。

ARCH=$(uname -m)
case "$ARCH" in
  x86_64) ARCH=amd64 ;;
  aarch64) ARCH=arm64 ;;
  *) echo "不支持的架构: $ARCH"; exit 1 ;;
esac

VER=v0.20.28
mkdir -p /opt/nezha/data && cd /opt/nezha
wget -4 "https://github.com/railzen/nezha-zero/releases/download/${VER}/dashboard-linux-${ARCH}.zip"
unzip -o "dashboard-linux-${ARCH}.zip"
chmod +x app
./app -v   # 应输出 0.20.28

步骤四:写 Dockerfile

在 /opt/nezha/Dockerfile 写入(参照官方 Dockerfile 的 busybox 方案,另加 CA 证书阶段):

FROM alpine AS certs
RUN apk update && apk add ca-certificates

FROM busybox:stable-musl
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
WORKDIR /dashboard
COPY app /dashboard/app
RUN chmod +x /dashboard/app
VOLUME ["/dashboard/data"]
EXPOSE 8008 5555
ENTRYPOINT ["/dashboard/app"]

步骤五:写 docker-compose.yml

在 /opt/nezha/docker-compose.yml 写入:

version: "3.8"

services:
  nezha:
    build:
      context: .
      # 纯 v6 机上 build 跑在隔离的 bridge 网络里,DNS 解析不了 Alpine 软件源,必须用 host
      network: host
    container_name: nezha-dashboard
    # Docker 端口映射默认只绑 IPv4,agent 走 v6 连 5555 进不来,直接 host 最省事
    network_mode: host
    restart: unless-stopped
    volumes:
      - ./data:/dashboard/data
    environment:
      - NZ_HTTPPORT=8008
      - NZ_GRPCPORT=5555
      - NZ_SITE_ADMINPASSWORD=${NZ_SITE_ADMINPASSWORD}

  cf-nezha:
    image: cloudflare/cloudflared:latest
    container_name: cf-nezha
    network_mode: host
    restart: unless-stopped
    command: tunnel --no-autoupdate run --token ${CF_TUNNEL_TOKEN}

步骤六:写 .env

在 /opt/nezha/.env 写入。注意这个文件里有 Tunnel Token,不要发到公开地方:

# 管理员初始密码,至少 10 位。首次启动后会写入 data/config.yaml 并转成哈希,
# 之后再改这里就没用了,要去面板设置页改
NZ_SITE_ADMINPASSWORD=改成你自己的强密码至少10位

# Cloudflare Tunnel token,下一步建好隧道后填进来
CF_TUNNEL_TOKEN=__CLOUDFLARE_TUNNEL_TOKEN__

步骤七:Cloudflare 建隧道

  1. 进 Cloudflare Zero Trust(one.dash.cloudflare.com)→ Networks → Tunnels → Create a tunnel,类型选 Cloudflared,起个名字如 nezha
  2. 把给出的 token 复制出来,填进上一步 .env 的 CF_TUNNEL_TOKEN
  3. 在隧道里 Add public hostname:
    • Subdomain 填 panel,Domain 选你的域名
    • Service Type 选 HTTP,URL 填 http://localhost:8008

原理:两个容器都是 host 网络,cloudflared 和 dashboard 共享宿主机网络栈,所以隧道出口直接指本机 localhost:8008 就行。

步骤八:启动并验证

cd /opt/nezha
docker-compose up -d --build
docker-compose ps
docker-compose logs -f nezha

日志里看到下面这行即成功:

NEZHA>> HTTP=8008, gRPC=5555

如果还看到 resource/template 找不到模板的报错,不用管,无害。

再看隧道这边的日志,出现 Registered tunnel connection 说明隧道已连上 Cloudflare:

docker-compose logs -f cf-nezha

然后浏览器打开 https://panel.example.com,用 admin + .env 里设的密码登录。

步骤九:改管理员密码

登录后进右上角 设置(/setting)直接改管理员密码即可。

如果想改文件也行:

cd /opt/nezha
docker-compose stop nezha
nano data/config.yaml
# 找到 site 下的 adminpassword,改成至少 10 位的新明文密码,保存退出
docker-compose start nezha
# 启动后程序会自动把明文转成哈希

步骤十:安全组放行 + 被控机接入

Scaleway 安全组(或别的云的防火墙)放行 TCP 5555,来源 ::/0。8008 走隧道,不用对外放行。

在面板里添加服务器拿到密钥,被控机上:

./nezha-agent -s [面板公网IPv6]:5555 -p 你的密钥 -d

注意 IPv6 地址要加方括号,例如 -s [2001:db8::1]:5555。被控机上线后,面板首页就能看到节点。

步骤十一:小硬盘清理

3G 硬盘经不起浪费,装完把没用的清掉:

# 安装包已解压完,删掉省约 29M
rm -f /opt/nezha/dashboard-linux-amd64.zip
# 构建缓存(这次构建攒了约 70M)
docker builder prune -f
# apk 缓存
apk cache clean
df -h   # 确认 / 还有足够空间

踩过的坑

  1. 没装 WARP 就开干:GitHub 和 Docker Hub 都是纯 IPv4,wget 和 docker pull 全部失败。先解决 IPv4 出站。
  2. build 报 fetch https://dl-cdn.alpinelinux.org 404/ERROR:docker build 的 RUN 步骤跑在隔离的 bridge 网络里,DNS 解析不了 Alpine 源(宿主机出站本身是好的)。修法:compose 的 build 段加 network: host。
  3. agent 连不上 5555:别用 ports 端口映射——纯 v6 机上 Docker 映射的端口默认只绑 IPv4,agent 走 v6 进不来。两个容器都用 network_mode: host 最省事。
  4. 改 .env 里的密码不生效:首次启动配置已写入 data/config.yaml 并转成哈希,之后改 .env 没用,去面板 /setting 改。
  5. 日志里 resource/template 报错:无害,忽略。
  6. 硬盘越用越满:定期 docker builder prune -f,zip 安装包用完即删。

常用运维命令

cd /opt/nezha
docker-compose logs -f nezha      # 看主控日志
docker-compose logs -f cf-nezha   # 看隧道日志
docker-compose restart nezha      # 重启主控
docker-compose stop nezha && docker-compose start nezha  # 同上
# 升级版本:换 release 包里的 app,重新构建
docker-compose down && docker-compose up -d --build

数据都在 /opt/nezha/data(config.yaml + sqlite.db),重建容器前备份这个目录就行。