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

Prism:给哪吒 v0 面板换一个前端 —— 功能介绍与 Docker 部署教程

哪吒面板(本文以 nezha-zero v0.20.28 为例)自带的前端胜在稳定,但信息密度和审美都比较「原生」:想一眼看全所有节点的速率、流量、价格、到期,还想有个像样的延迟图,就得自己动手换前端。Prism 就是这样一个第三方前端主题:基于开源项目 Monitor-Glass(作者 wxte,MIT 协议)深度改造,把数据层对着 nezha-zero 的面板重写了一遍,成品跑在 v0.passall.us,这篇文章把它的功能和完整部署方法一次讲清。

一、功能介绍

实时节点列表。数据走面板的 WebSocket(/ws)实时推送,一行一台机器:状态、名称、地区、系统、在线时长、上下行速率、累计流量、CPU、内存、硬盘、价格、到期,全部紧凑排布;速率和流量的上下行用定宽数字对齐,扫一眼就能对比。列表按面板里的显示顺序(DisplayIndex)排序,分组筛选直接用面板的标签(Tag)。

顶部状态条。在线/总数、实时上下行速率与累计流量、最忙节点(CPU 最高)与最快节点(下行最快),名字和数值带流光渐变,超阈值时火焰/闪电图标会呼吸提醒。

节点详情抽屉。点任意一行从右侧滑出:最上方是运营商延迟图(联通 v4/v6、移动 v4/v6 四条线,带丢包率,1h/6h/12h/24h 切换,可平滑、可拖动缩放);下面是系统信息、资源、网络与连接、服务四组信息并排两行 —— 系统版本、架构、CPU 型号、内存/交换/硬盘用量、进程数、IP 双栈状态、价格、到期、计费方式(单向/双向)、套餐流量、每月流量重置日,一屏看完不用滚。

独立详情页。每个节点有 /node/:id 详情页:CPU、内存、网络速率、硬盘四张历史曲线,外加运营商延迟大图。

点阵世界地图。列表下方是一张 330×133 的点阵世界地图(Natural Earth 数据栅格化):节点按上报国家落点,最忙/最快节点有脉冲光圈,离线节点玫红标记,海岸线上有流光扫过,点标记能看节点明细。小细节:没有南极洲节点时,南极洲大陆自动隐藏,有 AQ 节点接入才显示。

价格与套餐信息零配置。价格、到期、套餐流量、计费方式都直接解析面板每台机器的 PublicNote,不用在前端再维护一份。今日/本月流量由浏览器本地按计数器差值累计(面板不提供历史接口,这是纯前端方案)。

颜值与适配。随机 4K 壁纸背景(接口出图)加半透明遮罩与点阵质感,深/浅两套配色;全英文界面;移动端有专门的紧凑布局(列表精简为 7 列、详情两行并排、延迟图缩小)。左下角还有访客 IP 卡片(国旗、IP、运营商,15 秒自动消失)。

二、部署(Docker)

整体结构:前端是 React + Vite 构建出的纯静态文件(dist),装进一个 nginx:alpine 容器;容器里的 nginx 除了发静态文件,还把面板相关路径反代到哪吒面板本体 —— 这是这套前端能工作的关键,缺了反代就没有数据。

前提:

  • 哪吒 v0 面板已在运行(本文面板地址示例 http://127.0.0.1:8008 ,请换成你自己的,必须以 / 结尾)
  • 部署机器装有 Docker 与 Docker Compose
  • 一个域名解析到部署机器(示例 v0.example.com)

部署包下载:不想自己构建的,直接到 GitHub 下载现成部署包:ypkin/prism-nezha Releases(prism-deploy.zip,含构建好的 dist 与全部部署文件),解压后从第 2 步开始即可;三个部署文件在仓库里也能单独查看。想从源码构建的,走下面第 1 步。

第 1 步:构建前端

# 在前端源码目录中执行
npm ci
npm run build

构建产物在 dist/ 目录。后续更新前端版本,重复这一步后替换部署目录里的 dist 即可。

第 2 步:准备部署目录

新建部署目录,放入四样东西:上一步的 dist/、下面的 Dockerfile、docker-compose.yml 和 nginx 配置模板 default.conf.template。

Dockerfile:

FROM nginx:alpine
COPY dist /usr/share/nginx/html
RUN chmod -R a+rX /usr/share/nginx/html
COPY default.conf.template /etc/nginx/templates/default.conf.template
ENV DOMAIN=_
ENV NEZHA=http://127.0.0.1:8008/
ENV NEZHA_ORIGIN=http://127.0.0.1:8008
EXPOSE 80

用的是官方 nginx 镜像的模板机制:容器启动时把模板里的 ${DOMAIN}、${NEZHA}、${NEZHA_ORIGIN} 替换成环境变量生成正式配置。

docker-compose.yml:

services:
  glass:
    build: .
    image: glass-frontend:latest
    container_name: glass-frontend
    restart: unless-stopped
    ports:
      - "127.0.0.1:8084:80"
    environment:
      - DOMAIN=_
      # 哪吒 v0 面板地址,必须以 / 结尾
      - NEZHA=http://127.0.0.1:8008/
      - NEZHA_ORIGIN=http://127.0.0.1:8008

只绑 127.0.0.1 是有意的:HTTPS 终止交给宿主机 nginx(或 Cloudflare 隧道)在外层做,容器只出 HTTP。

default.conf.template(实际在用的完整配置):

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name ${DOMAIN};
    client_max_body_size 100m;

    root /usr/share/nginx/html;
    index index.html;

    # Monitor Glass 前端本体(SPA)
    location = / {
        try_files /index.html =404;
        add_header Cache-Control "no-cache, must-revalidate";
    }
    location / {
        try_files $uri $uri/ /index.html;
    }
    location /assets/ {
        try_files $uri =404;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }

    # Monitor Glass 适配层:面板首页快照(内含服务器列表与 PublicNote)
    location = /panel-snapshot {
        proxy_pass ${NEZHA};
        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;
    }
    # 主题里的「登录」入口指向 /admin/,转到面板登录页
    location = /admin {
        return 302 /login;
    }
    location = /admin/ {
        return 302 /login;
    }

    # 哪吒 v0 实时数据(v190 的唯一后端通道)
    location /ws {
        proxy_pass ${NEZHA}ws;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }



    # 面板后台入口:登录页与管理 SPA 整段透传给面板(不带 URI 的 proxy_pass 保持原路径)
    location = /login {
        proxy_pass ${NEZHA_ORIGIN};
        proxy_http_version 1.1;
        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;
    }
    location ^~ /dashboard {
        proxy_pass ${NEZHA_ORIGIN};
        proxy_http_version 1.1;
        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;
    }


    # 面板 OAuth 登录回调(GitHub 登录等)
    location ^~ /oauth2 {
        proxy_pass ${NEZHA_ORIGIN};
        proxy_http_version 1.1;
        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;
    }

    # 面板静态资源:渲染器 mixin.js、Vue/jQuery/echarts 都从这里加载
    location /static/ {
        proxy_pass ${NEZHA}static/;
        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;
    }

    # 保险:主题或后续版本可能用到的后端路径,透传给面板
    location /api/ {
        proxy_pass ${NEZHA}api/;
        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;
    }
    location = /service {
        proxy_pass ${NEZHA}service;
        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;
    }
}

几个不能省的点:

  • /panel-snapshot 是数据适配层:前端从面板首页 HTML 里解析出服务器列表和每台的 PublicNote(价格/到期/套餐),没有它列表就是空的。
  • /ws 必须带 Upgrade 头,否则实时数据连不上,页面只剩骨架。
  • /login、/dashboard、/oauth2 透传之后,从前端域名就能直接登录管理面板,后台和前台同域,省去记面板地址。
  • NEZHA 结尾的斜杠不能丢:模板里是 ${NEZHA}ws、${NEZHA}static/ 这样拼接的,少个斜杠路径就错位。

第 3 步:启动容器

docker compose up -d --build
docker ps --filter name=glass-frontend

看到容器 Up 即启动成功,本机 curl http://127.0.0.1:8084/ 应返回前端首页 HTML。

第 4 步:外层反代与 HTTPS

宿主机 nginx 加一个 server 块把域名转给容器(证书申请略,DNS-01 或 HTTP-01 均可):

server {
    listen 443 ssl;
    server_name v0.example.com;

    ssl_certificate     /path/to/v0.example.com.crt;
    ssl_certificate_key /path/to/v0.example.com.key;

    location / {
        proxy_pass http://127.0.0.1:8084;
        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_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

注意外层也要透传 WebSocket 的 Upgrade 头,不然实时通道在这一层断掉。用 Cloudflare 隧道的同理,把隧道回源指向 127.0.0.1:8084 即可。

第 5 步:验证

浏览器打开 https://v0.example.com ,依次确认:

  1. 节点列表出现且数字在跳动(/ws 已通);
  2. 点任意节点,抽屉里运营商延迟图有曲线(面板里需已配置 ICMP 监控任务);
  3. 价格/到期显示正确(对应机器的 PublicNote 已按面板格式填写);
  4. 访问 /login 能打开面板登录页并正常登录。

三、日常更新

前端发新版时:重新构建得到新 dist,替换部署目录里的 dist,然后:

docker compose up -d --build

静态资源带 hash 文件名且长缓存,入口 HTML 不缓存,用户刷新即可拿到新版,不用手工清缓存。

四、注意事项

  • 面板版本:本前端的数据解析针对 nezha-zero v0.20.28 的首页结构,面板大版本升级后若首页结构变化,需要同步适配 /panel-snapshot 的解析。
  • 历史曲线(详情页与今日流量)是前端在浏览器里采样累计的,换浏览器或清缓存会重新累计,这是无后端历史接口时的取舍。
  • 延迟图的数据来自面板的监控任务:先在面板里建好对联通/移动等目标的 ICMP 监控并分配给节点,前端才有数据可画。
  • 容器只绑 127.0.0.1 时不要忘了外层反代同样要放行 WebSocket。

换前端不动面板本体和 agent,翻车了把域名解析切回面板原地址即可回滚,整个过程对监控数据零影响。