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 ,依次确认:
- 节点列表出现且数字在跳动(/ws 已通);
- 点任意节点,抽屉里运营商延迟图有曲线(面板里需已配置 ICMP 监控任务);
- 价格/到期显示正确(对应机器的 PublicNote 已按面板格式填写);
- 访问 /login 能打开面板登录页并正常登录。
三、日常更新
前端发新版时:重新构建得到新 dist,替换部署目录里的 dist,然后:
docker compose up -d --build静态资源带 hash 文件名且长缓存,入口 HTML 不缓存,用户刷新即可拿到新版,不用手工清缓存。
四、注意事项
- 面板版本:本前端的数据解析针对 nezha-zero v0.20.28 的首页结构,面板大版本升级后若首页结构变化,需要同步适配 /panel-snapshot 的解析。
- 历史曲线(详情页与今日流量)是前端在浏览器里采样累计的,换浏览器或清缓存会重新累计,这是无后端历史接口时的取舍。
- 延迟图的数据来自面板的监控任务:先在面板里建好对联通/移动等目标的 ICMP 监控并分配给节点,前端才有数据可画。
- 容器只绑 127.0.0.1 时不要忘了外层反代同样要放行 WebSocket。
换前端不动面板本体和 agent,翻车了把域名解析切回面板原地址即可回滚,整个过程对监控数据零影响。