给 NAS 上的 mihomo 换个现代面板

家里 NAS 上的代理内核跑了大半年,面板却一直停留在四年前的版本:一百多个节点平铺在一个下拉框里,想找个延迟低的得一个个点。这篇文章记录换面板、写幂等脚本、自动分组的全过程。为免广告嫌疑,文中不出现具体的服务商与客户端名称。

起因:那个 2022 年的面板

NAS 上的管理面板是浏览器里默认端口打开的那个页面。能用,但实在谈不上好用——节点列表就是一长串纯文本,
一百多个节点塞在一个下拉框里,连「按延迟排序」都没有。

顺手查了一下,这个面板最后一次提交停在 2023 年,最后一个版本是 2022 年 11 月发的。四年没更新,难看是有原因的。

先摸清家底,再动手

换面板之前,第一件事是搞清楚「我到底在跑什么」。这件事的收益远超预期——后面所有的判断都建立在这次摸底上。

几个关键发现:

  • 内核是 mihomo(Clash.Meta),控制器 API 开在 :9090,而且没有设访问密码;
  • 节点是内联在配置里的(不是 proxy-providers),这直接决定了后面分组方案的选择;
  • 12 个策略组,每组都塞了一百多个节点,也就是说同一份扁平长列表被重复了 12 遍;
  • 更关键的是:117 个节点里只有 53 个有过测速记录——一半以上的节点从没测过速。

最后一条基本解释了「选节点为什么这么痛苦」:不是面板不努力,是它压根没帮你测过。

选面板:三个候选

面板 维护状态 特点
zashboard 几乎每天有提交,最新版 2026-09 节点卡片网格、右键卡片整组测速、搜索、PWA、可改键位
metacubexd 活跃,内核官方推荐 32 套主题、7 种语言、规则搜索带命中数
yacd-meta 活跃(yacd 的续命分支) 界面和原来一样,改动最小
yacd 2022 年后停更 就是原来那个

最后选了 zashboard,理由是它对「选节点」这个动作的优化最直接:右键节点卡片只测这一个,
右键组卡片整组一起测,然后按延迟排序。

部署:让内核自己托管面板

常规做法是起一个 nginx 容器托管静态文件,但 mihomo 有个更省事的能力:它可以直接把自己的 API 端口当成静态服务器。

1
2
3
4
5
external-ui: ui
external-ui-name: zashboard
unified-delay: true
profile:
store-selected: true

把面板的静态文件解压到内核工作目录下的 ui/zashboard/,重启即可通过 http://<NAS>:9090/ui/zashboard/ 访问。

三个好处:

  • 同源:面板和 API 在同一个端口,不用配跨域,也不用额外维护一个容器;
  • 内核日志会明确写出 UI already exists, skip downloading,不会偷偷覆盖你的文件;
  • 顺带解锁了 unified-delay。

unified-delay 为什么重要:不同协议(Trojan / VLESS / AnyTLS 等)的握手开销不一样,不统一延迟的话,测出来的数字根本没法横向比较,排序也就失去了意义。

解压 release 包时注意:很多包的最外层是 dist/,要让 index.html 直接躺在 ui/zashboard/ 下,否则打开只会看到一个 404 页面。

踩坑:服务商配置会覆盖你的设置

换完面板没两天,更新了一次订阅,然后发现:

  • 面板打不开了——新配置把 external-controller 从 0.0.0.0:9090 改成了 127.0.0.1:9090;
  • 局域网其它设备不能再用这个代理了——allow-lan 被改成了 false;
  • 出问题没有任何日志——log-level 被改成了 silent。

订阅配置并不「知道」你在拿它做局域网网关。所以需要一个幂等的后处理脚本,每次订阅更新后跑一次:

  1. 规范化这几个关键项;
  2. 补齐面板相关设置;
  3. 重新生成自定义分组;
  4. 用内核自己的 -t 参数校验候选配置,不通过就一个字节都不替换;
  5. 备份 → 替换 → 重启 → 等到内核真正就绪再返回。

第 5 步别省。内核加载 GeoIP 数据库要 10 秒以上,如果脚本重启完立刻返回,紧接着的检查会全部失败,很容易误判成「配置把内核搞崩了」——我就这么误判过一次。

进阶:按落地地区自动分组

面板好看了,但「一百多个节点塞在一个下拉框里」这个问题还在。

节点命名其实有规律:<入口机房>转<落地地区><代号>[协议][倍率:x]。于是写了个脚本,按落地地区自动生成分组:
日本、台湾、香港、美国、新加坡等等,再加一个「省钱组」(倍率 ≤ 0.6 的节点)。

两个关键设计:

  • 取最后一次「转」之后的部分作为落地地区。A转美国X 应该归到美国,而不是被名字里的「A」带偏;
  • 新组名追加到主选择组末尾,而不是插到开头。因为 select 组的默认值是列表第一项,插到开头会静默改变你现有的默认走向——这种 bug 最难查。

脚本还要幂等:重跑时先按名字删掉旧的自建组再重建,两次运行结果字节一致。

改造完的体感是这样的:打开面板,十几个地区分组一目了然,每组里的节点都按测速结果排好序,右键组卡片就能整组重测;
常用的几个组直接放在主选择组的最前面。选节点从「翻一百多行列表」变成了「点两下」。

几条经验

  1. 先摸家底再动手。 「有多少节点、测过几个、API 有哪些字段」这些问题,决定了后面能用什么方案。比如节点是内联还是 provider,直接决定了分组能不能用 filter。
  2. 让内核托管面板。 少一个容器、少一个跨域问题,还顺带能同步设置。
  3. 订阅配置会重置你的设置。 任何「更新后要重做一遍」的事,都该写成幂等脚本,并且必须在替换前用内核自己校验。
  4. 追加,不要插入。 改别人的策略组时,注意默认值语义。
  5. 备份先行。 每次替换配置前留一份带时间戳的备份,回滚成本就只剩一条 cp 命令。

最后一个教训(关于隐私)

这次折腾里我犯了个错:排查问题时顺手把配置文件的第一行打印了出来,而那一行恰好是带 token 的订阅链接。
在自动化工具里,「打印出来」就等于「上传出去」。

后来给自己定了条规矩,也分享给同样爱折腾的人:

  • 涉及凭据的操作,写成脚本让脚本读,只打印聚合结果(数量、状态码、可用率);
  • 需要交互输入时用不回显的方式(getpass / read -rsp),不进命令行参数、不进 shell 历史;
  • 万不得已要展示,只给「长度 + 前缀几位」;
  • 排查任何文件时,先看结构特征(长度、字符集、熵、魔数),不要为了找线索把整个文件 cat 出来。

能自动化是本事,把凭据一起贴出去就是事故了。


给 NAS 上的 mihomo 换个现代面板
https://chaggle.github.io/2026/10/16/linux/mihomo-nas-dashboard-20261017/
作者
chaggle
发布于
2026年10月16日
更新于
2026年10月17日
许可协议