别再手改 frpc.toml 了:我给内网穿透做了个 Web 面板,叫 Nodus
·(編集済み)· / , , , , · 閲覧0
Nodusはfrpc用のWeb管理パネルで、frpクライアント、内网穿透プロキシルール、接続状態を一元管理し、設定変更やログ確認といったターミナル作業をブラウザのクリック操作に置き換えます。オープンソースプロジェクトpoduxから派生しており、データ構造は互換性があるため既存ユーザーはそのまま移行できます。主な機能はマルチノード管理、可視化プロキシルール、リアルタイムログ、ネットワーク監視、ダッシュボード、権限管理、設定インポートなど。デプロイはスクリプト・Docker・バイナリの3方式で、デフォルトのアカウント・パスワードはありません。セキュリティ面では権限昇格の脆弱性を修正し、機密情報をログに残さないようにしました。2日間で7リリースを重ねる早期段階のv0.0.xで、ライセンスはApache 2.0。重要な前提として、frpsサーバーは各自で用意する必要があり、Nodusはクライアント側の管理のみを担います。
人在外面,想连回家里内网的某台机器。于是打开终端,ssh 上去,vim 打开 frpc.toml,把端口改了一个数字,重启 frpc,然后盯着日志看它有没有起来。
改对了,长舒一口气;改错了,日志刷了一屏英文,从头排查。
如果你也在用 frp 做内网穿透,这个循环大概率眼熟。而我一直想问的是:为什么 2026 年了,管几个内网穿透规则还跟在编辑器里搬砖一样?
于是就有了 Nodus。
项目入口:本站项目列表 · Nodus 仓库 · 最新发布。本站项目卡片会打开对应仓库,下载、文档和问题反馈仍以仓库为准。
一、30 秒说清楚:Nodus 是什么
一句话:Nodus 是 frpc 的 Web 管理面板,用来集中管理 frp 客户端、内网穿透代理规则与连接状态。
具体说:
项目在这里:
Nodus 项目仓库(GitHub)。
先交代来源:Nodus 是从 podux 这个项目来的。podux 已经把"给 frpc 做个面板"这件事跑通了,Nodus 是在它基础上的二次开发——数据结构保持兼容,所以老用户的 pb_data 可以直接拷过来(第七节细讲)。我从它那儿拿了什么,又改了什么,具体看下面的对比。
一句话版本,我自己的说法是:把"配置文件 + 终端 + 猜状态"变成"浏览器里点几下"。
顺便说一个观察(这是我的观点,不是官方定位):frp 自带的 dashboard 以服务端(frps)视角为主,看的是"这台服务端上都有哪些代理在跑";而日常要反复增删改查、盯着看日志的,往往是你手上的客户端那侧。Nodus 想补的就是这个位置。
和原项目 podux 的区别:我改了什么
先说明来源:podux 是上游,Nodus 是从它来的,不是从零重写。所以下表列的都是增量——基本盘(多节点、代理规则、日志、配置导入)在 Nodus 里原样保留,我动的是它之外的部分。两个仓库都在更新,具体以各自 README 为准。
区别点
Nodus 相对 podux 的变化
上游与数据兼容
数据结构与 pb_data 兼容,podux 的老数据可以直接拷进 Nodus,不用重配一遍
网络监控
新增延迟探测与服务器地理位置信息
数据大盘
新增节点拓扑与连接统计的可视化视图
权限模型
新增管理员 / 普通用户两级角色,写操作必须是管理员;v0.0.3 专门修了一版角色提权漏洞
迁移工具
新增 migrate-to-nodus.sh,支持 podux / frpc-hub / frpc 三种来源,带 --dry-run 预览与自动备份;迁移指南里还附了一段可以直接粘给 AI Agent 的迁移指令
工程与文档
独立的 v0.0.x 版本节奏、golangci-lint 清零、内置 frp 跟到 v0.71.0;中文文档五篇(快速开始、迁移指南、配置说明、安装部署、API 与开发)
许可与协作
Apache 2.0,问题直接在 GitHub issue 走
一句话概括区别:podux 证明了方向,Nodus 把它补成一个能长期维护、能给别人接手的项目——多节点之外补了监控和大盘,配置之外补了权限,升级之外补了迁移路径。
Nodus 管理 frpc,不替你部署公网 frps。访问业务服务时,数据经过隧道;打开面板看到一个节点,并不等于业务已经可以从外面访问。
二、frpc 到底哪里难用:三个老毛病
先说做这个面板的原因。frp 本身是个非常好的项目,但它的客户端日常使用,有三个反复出现的摩擦点:
其一,一切都在 frpc.toml 里。
改一个端口要动文件、要重启进程;写错一个字段,客户端起不来,而原因只在日志的某一行里。配置即代码,可惜没人给它做 lint,也没人给它做回滚。
其二,多节点 = 多开。
家里一台机器、云上一台 VPS、单位一台,每个节点一份配置、一份日志、一个进程。想看第三个节点的状态,就得再开一个终端窗口,再 ssh 一次。
其三,"它到底连上了吗"是玄学。
没有一个直观的全局状态视图。连接断没断,得翻日志、ping 一下、靠猜。
这三条是我在实际使用 frpc 时反复撞到的摩擦点——也正是我想用一个面板解决掉的三件事。
三、现在能用的九项功能
README 里写的是"基于当前代码实现",也就是说下面这些不是路线图,是现在就能用的东西:
功能
它解决什么
多节点管理
同时接入多个 frps 服务器(frpc 客户端节点),统一启动 / 停止 / 重载
代理规则管理
可视化配置 tcp / udp / http / https 代理(stcp / xtcp 在界面中已预留)
连接与日志
查看节点运行状态,实时输出 frpc 日志
网络监控
延迟探测与服务器地理位置信息
数据大盘
节点拓扑与连接统计
开机自启
节点配置 autoConnection 后随服务自动启动
配置导入
导入现有 frpc.toml,批量生成服务器与代理
权限控制
管理员 / 普通用户角色,写操作需管理员
版本检查
界面内查看当前版本与最新 Release
其中几项要单独说:
常规设置可以分别调整延迟检测和位置检查的间隔。图中显示 30 秒和 60 秒,是本地演示环境的设置值,不是测得的网络延迟。实际节点是否连通,还要看连接状态、日志和业务访问结果。
四、5 分钟跑起来:三种部署方式
Nodus 默认端口是 8090。三种方式任选其一。
但先说一个不能省的前提:只装 Nodus,你什么都穿不通。Nodus 管的是客户端(frpc)这一侧,隧道本身要靠 frps 服务端。你必须先在一台有公网 IP 的机器上把 frps 部署起来,面板里的节点才有地方连;不部署 frps,Nodus 装得再漂亮也只是个空壳。
frps 的最小配置长这样:
起服务端:frps -c frps.toml。同时记得在云厂商的安全组 / 防火墙里放行 7000 以及你各条代理要用到的端口,否则客户端照样连不上。配置里的 auth.token 记下来,等下在面板"添加节点"时要填。如果你已经有在跑的 frps,这一步直接跳过。
方式一:一键脚本
支持的环境变量:PORT(默认 8090)、IMAGE、CONTAINER_NAME、VOLUME_NAME、MODE=docker|binary。完整说明见仓库里的搭建教程。
方式二:Docker
或者用仓库自带的 compose:
想锁版本(生产环境建议锁):
方式三:二进制
到 Releases 下载对应平台的压缩包(文件名含版本号),然后:
装完访问 http://<服务器>:8090,按界面提示创建管理员账号。
五、关于登录:为什么没有默认账号
这是很多人第一次上手会愣一下的地方:
Nodus 没有预置的默认账号密码,首次访问时引导你自行创建。
我认为这是必须的。自托管工具最经典的翻车方式之一,就是"装完忘了改默认密码",然后被扫描器扫到。没有默认密码,就不存在这个事故。
系统有三个入口:
登录入口
地址
说明
用户端(主界面)
http://<服务器>:8090
首次访问创建的邮箱 + 密码,用于管理服务器和代理
管理后台(PocketBase Admin)
http://<服务器>:8090/_/
首次访问时创建的超级管理员邮箱 + 密码,用于数据库管理
frps 服务端令牌
—
添加服务器节点时需填写 frps 的 auth.token,由你的 frps 配置决定
两点补充:
编辑服务器时,先对上 frps 的主机、连接端口、版本和认证,再看日志与传输选项。认证区里的令牌保持隐藏;TLS 证书字段属于连接设置,不是业务服务的端口。图中是本地演示节点,自动连接关闭,未建立真实隧道。
用户端账号、PocketBase 超级管理员和 frps 令牌不能互换。图里不放任何实际密码;添加服务器需要的令牌,应和已有 frps 配置对应。
六、一条典型工作流:装好之后我会怎么用
这七步跑完,你会发现原来那套"ssh + vim + 重启 + tail"的循环,基本消失了。
用一个 TCP 服务把字段对上
第一次新建规则,不必同时配置好几个服务。假设本地 Web 服务监听在 8080,准备通过 frps 的 18080 端口访问它,先确认 Nodus 所在机器能访问这个本地服务,再填代理。
服务器页填的是 frps 的地址、连接端口和认证方式;它不是你的业务服务地址。上图用本机 127.0.0.1:17000 做界面演示,节点保持停止,未连接真实 frps,也没有开放公网端口。正式使用时,换成你已经部署好的 frps 地址、端口与令牌。
在代理页选中服务器,名称填 demo-web,类型选 TCP;本地地址和本地端口指向业务服务,远程端口填 frps 一侧对外提供服务的端口。截图里的 8080 → 18080 是字段映射示例。这张图截于填写阶段;补充演示中已把规则保存到本地,但节点仍未启动,不代表隧道已通。
本地地址里的 127.0.0.1 指的是 frpc 运行环境自身。如果 Nodus 跑在容器里,它通常不是宿主机,更不是另一台内网设备。先确认这层地址,再检查 frps 的监听端口、认证与防火墙。规则保存后还要启动节点、看日志,并从外部访问业务端口;“已保存”和“服务可访问”是两次不同的检查。
选择 HTTPS 后,表单仍按域名或子域名组织规则。这个例子填本地 127.0.0.1:8443 和子域名 photo,只用于对照字段,没有提交规则、配置证书或验证 TLS 访问。选了 HTTPS 类型,不等于证书和服务端监听已经准备好。
首次跑通后,再决定是否开启自动连接。已有配置则优先走导入,不必照着编辑器逐条重填。字段说明见配置文档。
换成 HTTP 后,表单不再让你填 TCP 的远程端口,而是出现自定义域名与子域名。这里用本地 3000 端口和 blog.example.com 做示例;域名只是占位,没有配置 DNS,也没有验证公网访问。真正使用时,还要对上 frps 的 HTTP 监听和域名解析。
列表把两个例子放在一起:TCP 一行显示远程端口,HTTP 一行显示域名。规则“已启用”和连接“在线”是不同状态;截图中两条规则都已保存、已启用,但因节点没启动而保持离线。不能看到“已启用”就认为服务已经能从外面访问。
图用正文的端口例子解释连接关系,不是已经运行的拓扑。frps 连接端口、对外业务端口和内网服务端口不同;容器里的 127.0.0.1 还要按容器环境理解。
UDP 表单保留本地地址、本地端口和远程端口;图中用 5353 → 15353 做字段示例。端口数字只是演示,不代表对应服务已经运行。这条规则没有提交,节点也没有启动;正式使用时还要检查 UDP 的安全组、防火墙和真实服务响应。
七、老用户搬家:三种来源都能迁
如果你本来就在用别的工具,迁移路径是这样的:
1. 来自 podux(github.com/luckjiawei/podux)/ frpc-hub
数据结构兼容,直接拷贝 pb_data 即可无损迁移。
2. 来自原生 frpc
用配置导入功能接入现有 frpc.toml。
3. 用脚本一把梭
脚本会自动备份、复制数据、启动 Nodus 并导入 frpc.toml;支持服务器上已有的 podux / frpc-hub / frpc 三种来源,找不到旧数据时按全新安装处理。
迁移指南里还有一个我觉得相当务实的细节:里面准备了可以直接发给 AI Agent 的自动迁移指令,以及手动迁移步骤和回滚方式。也就是说,你可以把那段指令直接粘给 Claude 或 Cursor,让它替你在服务器上跑完。这类"给 AI 用的文档"以后应该会越来越多。
现有 frpc.toml 可以先解析成预览,逐条核对服务器、代理名称、本地地址和远端字段。图中检测到相同地址与端口的服务器,并提供是否覆盖的选择。这次只解析示例 TOML、停在预览,没有确认导入或覆盖任何节点;正式迁移前先备份旧数据,再决定保留、合并还是覆盖。
原生 frpc 走配置导入,podux/frpc-hub 则涉及兼容的数据目录。脚本执行前先预览和备份,再核对结果;图不是本次已经完成了一次迁移的证明。
八、往深了说:它是怎么造出来的
如果你只关心用法,上面就够了。这一节写给想读源码、或者想自己维护类似项目的人。
技术栈
组件
版本
Go
1.25
PocketBase
0.35.0
frp
0.71.0
React / TypeScript / Vite
19 / 5.9 / 7
为什么选 PocketBase
PocketBase 给了一个 Go 内嵌的后端骨架:SQLite 存储、鉴权、文件、管理后台,全在一个二进制里。对这种"个人或小团队用的自托管面板"来说,它的性价比很高——省掉了自研用户系统,/_/ 还能直接当数据库控制台用。
代价是:表结构管理必须有纪律,否则版本一升就乱。所以这个项目把 migrations/ 定为 PocketBase 集合结构的唯一真相源,而且要求每个迁移都是可回滚的 .go 文件;不允许通过改线上 SQLite、或者在管理后台手动改 schema 来绕过它。
分层与依赖方向
依赖方向是固定的 interfaces → application → domain,基础设施实现领域层定义的接口,main.go 负责集中装配(启动、hooks、监控调度、静态资源服务)。这条规矩看着朴素,但它决定了项目在长出十几个月后还能不能改得动——接口层永远不许直接摸数据库。
请求进来先经过传输层和用例编排,持久化实现则遵守领域层定义的接口。箭头表示依赖或装配关系,不是网络数据包在这几层间移动的真实抓包;领域层不依赖 PocketBase。
前端:site/ 目录
一个容易误会的点顺便澄清:docs/ 文档站是 VitePress(Vue 生态),但这不代表应用前端用了 Vue——应用前端是 React。文档是独立的一站。
单二进制背后的小设计
site/dist 会被拷贝到 pb_public/,再由 main.go 用 go:embed 打进 Go 二进制里。所以前端构建产物是 Go 构建的前置条件——这也是为什么验证流程长这样:
单二进制不是省掉前端构建,而是把已构建的前端资源嵌入进去。没有 pb_public 里的资源,后面的 go:embed 就没有可嵌入的文件。
九、安全:做了什么,也明确不做什么
这类工具的威胁模型其实很朴素:它手里握着你所有内网入口的凭据。所以仓库里写了几条红线:
写项目文档的人愿意把"我们明确不做什么"列出来,通常比列功能更能说明成熟度——至少说明写的人真的想过哪里会出事。
十、版本节奏:两天七个版本
截至发稿,版本历史是这样的:
日期
版本
内容
2026-09-25
v0.0.1
Nodus 首个版本
2026-09-25
v0.0.2
安全加固与全面缺陷修复
2026-09-25
v0.0.3
修复角色提权漏洞与文档资产名
2026-09-26
v0.0.4
文案修正、golangci-lint 清零、UI 作者署名更新
2026-09-26
v0.0.5
登录说明、版本号修复、代理页面访问按钮
2026-09-26
v0.0.6
内置 frp 升级至 v0.71.0
2026-09-26
v0.0.7
frp 代理名不再拼接 ID 后缀,frps 显示友好名称
我的读法是这样的:
同时它也说明另一件事:这是个非常早期的 v0.0.x 项目。迭代快是优点,但你得接受它还在动。
十一、它适合谁,不适合谁
适合你,如果:
先掂量一下,如果:
十二、写在最后
回到开头那个场景:改一个端口,原来要 ssh、vim、重启、看日志四步。现在是打开面板,改,保存,它自己重载。
Nodus 想做的事情,说白了就一句话:让内网穿透的管理回到"点几下鼠标"的正常水平。
它现在还很小,star 也不多。但一个两天推了七个版本、把提权漏洞放在第三版就修掉、把"别把密钥打进日志"写进红线的项目,值得你花五分钟部署一个试试——前提还是那句:frps 得你自己先备好。
有问题直接开 issue,我都在。
附录:速查卡
前提:先有 frps(不部署就用不了)
这个 auth.token 就是面板"添加节点"时要填的那个。
部署
迁移
三个入口
忘记密码:进 /_/,在 fh_users 集合中重置。