“从一句配置文件的痛,到一个能跑起来的开源项目。这篇从头讲:Nodus 是什么、它和上游 podux 的区别、怎么用、老配置怎么迁、以及它是怎么造出来的——对了,frps 服务端还得你自己部署。人在外面,想连回家里内网的某台机器。于是打开终端,ssh 上去,vim 打开 frpc.toml,把端口改了一个数字,重启 frpc,然后盯着日志看它有没有起来。改对了,长舒一口气;改错了,日志刷了一屏英文,从头排查。如果你也在用 frp 做内网穿透,这个循环大概率眼熟。而我一直想问的是:为什么 2026 年了,管几个内网穿透规则还跟在编辑器里搬砖一样?于是就有了 Nodus。项目入口:本站项目列表 · Nodus 仓库 · 最新发布。本站项目卡片会打开对应仓库,下载、文档和问题反馈仍以仓库为准。一、30 秒说清楚:Nodus 是什么一句话:Nodus 是 frpc 的 Web 管理面板,用来集中管理 frp 客户端、内网穿透代理规则与连接状态。具体说:它管的是客户端(frpc)这一侧——你有哪些节点、每个节点上挂了哪些代理规则、它们连没连上、日志在说什么。它不是 frps 服务端,也不替代隧道本身——frps 得你自己部署。frp 照常跑你的流量,Nodus 管的是"怎么配、怎么看"。一个浏览器标签页,替代一堆终端窗口。项目在这里: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其中几项要单独说:配置导入是最能减少迁移成本的一条。你不用照着手册一条条重敲,把现成的 frpc.toml 丢进去,它批量生成服务器与代理。实时日志解决"玄学"问题。以前是 ssh 过去 tail -f,现在是界面上直接看 frpc 在刷什么。stcp / xtcp 目前只是在界面中预留,还没开放——写在这里是为了不让你抱着错误预期点进去。权限控制是为多人准备的:普通用户可以看,写操作(增删改节点和代理)必须是管理员。常规设置可以分别调整延迟检测和位置检查的间隔。图中显示 30 秒和 60 秒,是本地演示环境的设置值,不是测得的网络延迟。实际节点是否连通,还要看连接状态、日志和业务访问结果。四、5 分钟跑起来:三种部署方式Nodus 默认端口是 8090。三种方式任选其一。但先说一个不能省的前提:只装 Nodus,你什么都穿不通。Nodus 管的是客户端(frpc)这一侧,隧道本身要靠 frps 服务端。你必须先在一台有公网 IP 的机器上把 frps 部署起来,面板里的节点才有地方连;不部署 frps,Nodus 装得再漂亮也只是个空壳。frps 的最小配置长这样:TOML複製# frps.toml —— 服务端,跑在有公网 IP 的机器上 bindAddr = "0.0.0.0" bindPort = 7000 auth.token = "换成你自己的强随机 token"起服务端:frps -c frps.toml。同时记得在云厂商的安全组 / 防火墙里放行 7000 以及你各条代理要用到的端口,否则客户端照样连不上。配置里的 auth.token 记下来,等下在面板"添加节点"时要填。如果你已经有在跑的 frps,这一步直接跳过。方式一:一键脚本BASH複製bash scripts/setup.sh支持的环境变量:PORT(默认 8090)、IMAGE、CONTAINER_NAME、VOLUME_NAME、MODE=docker|binary。完整说明见仓库里的搭建教程。方式二:DockerBASH複製docker run -d \ --name Nodus \ --restart unless-stopped \ -p 8090:8090 \ -v Nodus-data:/app/pb_data \ sexyfeifan/nodus:latest或者用仓库自带的 compose:BASH複製docker compose -f deploy/docker-compose.yml up -d想锁版本(生产环境建议锁):BASH複製docker pull sexyfeifan/nodus:0.0.7方式三:二进制到 Releases 下载对应平台的压缩包(文件名含版本号),然后:BASH複製tar -xzf Nodus-v0.0.7-linux-amd64.tar.gz ./Nodus serve --http 0.0.0.0:8090装完访问 http://<服务器>:8090,按界面提示创建管理员账号。五、关于登录:为什么没有默认账号这是很多人第一次上手会愣一下的地方:Nodus 没有预置的默认账号密码,首次访问时引导你自行创建。我认为这是必须的。自托管工具最经典的翻车方式之一,就是"装完忘了改默认密码",然后被扫描器扫到。没有默认密码,就不存在这个事故。系统有三个入口:登录入口地址说明用户端(主界面)http://<服务器>:8090首次访问创建的邮箱 + 密码,用于管理服务器和代理管理后台(PocketBase Admin)http://<服务器>:8090/_/首次访问时创建的超级管理员邮箱 + 密码,用于数据库管理frps 服务端令牌—添加服务器节点时需填写 frps 的 auth.token,由你的 frps 配置决定两点补充:忘记用户端密码时,可以进 PocketBase Admin 后台,在 fh_users 集合里重置。添加节点时要的 auth.token 来自你自己的 frps 服务端配置,不是 Nodus 这边生成的。编辑服务器时,先对上 frps 的主机、连接端口、版本和认证,再看日志与传输选项。认证区里的令牌保持隐藏;TLS 证书字段属于连接设置,不是业务服务的端口。图中是本地演示节点,自动连接关闭,未建立真实隧道。用户端账号、PocketBase 超级管理员和 frps 令牌不能互换。图里不放任何实际密码;添加服务器需要的令牌,应和已有 frps 配置对应。六、一条典型工作流:装好之后我会怎么用先部署 frps —— 服务端跑在有公网 IP 的机器上,放行端口、备好 auth.token。没有 frps,下面每一步都白搭。部署 —— 三种方式挑一个,起来之后创建账号。添加节点 —— 填 frps 服务端地址和 auth.token。有多个 frps 就多加几个。导入规则 —— 已经有 frpc.toml 的,走配置导入,批量生成服务器与代理;全新开始的就手点。确认状态 —— 到"连接与日志"看节点是不是连上了,实时日志里有没有报错。勾开机自启 —— 节点配 autoConnection,服务重启后自动拉起,不用再手动点一次。平时只开两个页面 —— "数据大盘"看拓扑和连接统计,"网络监控"看延迟和地理位置;出问题了才点开日志。这七步跑完,你会发现原来那套"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. 用脚本一把梭BASH複製# 先预览,再执行 bash scripts/migrate-to-nodus.sh --dry-run bash scripts/migrate-to-nodus.sh脚本会自动备份、复制数据、启动 Nodus 并导入 frpc.toml;支持服务器上已有的 podux / frpc-hub / frpc 三种来源,找不到旧数据时按全新安装处理。迁移指南里还有一个我觉得相当务实的细节:里面准备了可以直接发给 AI Agent 的自动迁移指令,以及手动迁移步骤和回滚方式。也就是说,你可以把那段指令直接粘给 Claude 或 Cursor,让它替你在服务器上跑完。这类"给 AI 用的文档"以后应该会越来越多。现有 frpc.toml 可以先解析成预览,逐条核对服务器、代理名称、本地地址和远端字段。图中检测到相同地址与端口的服务器,并提供是否覆盖的选择。这次只解析示例 TOML、停在预览,没有确认导入或覆盖任何节点;正式迁移前先备份旧数据,再决定保留、合并还是覆盖。原生 frpc 走配置导入,podux/frpc-hub 则涉及兼容的数据目录。脚本执行前先预览和备份,再核对结果;图不是本次已经完成了一次迁移的证明。八、往深了说:它是怎么造出来的如果你只关心用法,上面就够了。这一节写给想读源码、或者想自己维护类似项目的人。技术栈组件版本Go1.25PocketBase0.35.0frp0.71.0React / TypeScript / Vite19 / 5.9 / 7为什么选 PocketBasePocketBase 给了一个 Go 内嵌的后端骨架:SQLite 存储、鉴权、文件、管理后台,全在一个二进制里。对这种"个人或小团队用的自托管面板"来说,它的性价比很高——省掉了自研用户系统,/_/ 还能直接当数据库控制台用。代价是:表结构管理必须有纪律,否则版本一升就乱。所以这个项目把 migrations/ 定为 PocketBase 集合结构的唯一真相源,而且要求每个迁移都是可回滚的 .go 文件;不允许通过改线上 SQLite、或者在管理后台手动改 schema 来绕过它。分层与依赖方向複製internal/interfaces/http 传输层:路由、参数校验、响应 ↓ internal/application 用例编排:dashboard / frpc / importer / monitoring / proxy / server … ↓ internal/domain 领域模型与仓储接口 internal/infrastructure/persistence 仓储实现(基于 PocketBase / dbx),实现 domain 的接口依赖方向是固定的 interfaces → application → domain,基础设施实现领域层定义的接口,main.go 负责集中装配(启动、hooks、监控调度、静态资源服务)。这条规矩看着朴素,但它决定了项目在长出十几个月后还能不能改得动——接口层永远不许直接摸数据库。请求进来先经过传输层和用例编排,持久化实现则遵守领域层定义的接口。箭头表示依赖或装配关系,不是网络数据包在这几层间移动的真实抓包;领域层不依赖 PocketBase。前端:site/ 目录React 19 + TypeScript 5.9 + Vite 7,UI 用 Radix Themes 3 + Tailwind CSS 4。组件拆分有明确约定:index.tsx 管状态与编排,*.view.tsx 管展示,请求统一走 site/src/lib/api.ts 或 pocketbase.ts。国际化:用户可见文案必须同时更新 site/src/locales/zh.json 和 en.json,并通过 react-i18next 的 t() 取用,不允许新增硬编码字符串。一个容易误会的点顺便澄清:docs/ 文档站是 VitePress(Vue 生态),但这不代表应用前端用了 Vue——应用前端是 React。文档是独立的一站。单二进制背后的小设计site/dist 会被拷贝到 pb_public/,再由 main.go 用 go:embed 打进 Go 二进制里。所以前端构建产物是 Go 构建的前置条件——这也是为什么验证流程长这样:TEXT複製site lint / build → docs build → 把 site/dist 拷进 pb_public/(go:embed 要求文件存在) → go vet ./... → go test ./... → go build ./...单二进制不是省掉前端构建,而是把已构建的前端资源嵌入进去。没有 pb_public 里的资源,后面的 go:embed 就没有可嵌入的文件。九、安全:做了什么,也明确不做什么这类工具的威胁模型其实很朴素:它手里握着你所有内网入口的凭据。所以仓库里写了几条红线:角色权限:管理员 / 普通用户,写操作必须是管理员。v0.0.3 专门发了一版修复角色提权漏洞——这点我后面还会讲,因为它是版本历史里最值得说的一条。敏感值绝不落日志:fh_servers.auth(frps 令牌)、TLS 私钥、用户密码、token 的原始值,不打印、不复制、不暴露。token 不放进 SSE 的 query 参数:URL 会进日志、进历史、进 Referer,这是最常见的凭据泄漏渠道之一。不提交 secrets:pb_data/、pb_public/、site/dist/、构建产物一律不进仓库。不用手工改库代替 migration;关系当前没有级联删除,所以删父记录前要自己评估会不会留下孤儿数据。端点、鉴权规则、数据结构一旦变更,必须同步更新测试、调用方和设计文档。写项目文档的人愿意把"我们明确不做什么"列出来,通常比列功能更能说明成熟度——至少说明写的人真的想过哪里会出事。十、版本节奏:两天七个版本截至发稿,版本历史是这样的:日期版本内容2026-09-25v0.0.1Nodus 首个版本2026-09-25v0.0.2安全加固与全面缺陷修复2026-09-25v0.0.3修复角色提权漏洞与文档资产名2026-09-26v0.0.4文案修正、golangci-lint 清零、UI 作者署名更新2026-09-26v0.0.5登录说明、版本号修复、代理页面访问按钮2026-09-26v0.0.6内置 frp 升级至 v0.71.02026-09-26v0.0.7frp 代理名不再拼接 ID 后缀,frps 显示友好名称我的读法是这样的:第一天的三版是"先让它能跑,再让它别出事":首版上车,第二版安全加固,第三版就抓到了角色提权漏洞并修掉——提权属于必须最优先处理的那类问题,尤其是对一个带权限模型的自托管面板。第二天的四版转向工程质量与体验:golangci-lint 清零意味着把静态检查彻底拉进流程;登录说明、访问按钮、代理名后缀这些,都是第一次真正上手的用户才会撞到的细节。v0.0.6 把内置 frp 升到 0.71.0,说明依赖不是装完就不管的,是有在跟着上游走。同时它也说明另一件事:这是个非常早期的 v0.0.x 项目。迭代快是优点,但你得接受它还在动。十一、它适合谁,不适合谁适合你,如果:你手上不止一个 frps 节点,不想每个都开个终端;你受够了手改 frpc.toml,想要可视化增删规则;你正在用 podux 或 frpc-hub,想换个维护活跃的、数据能直接拷过来的;你想看状态和日志,而不是靠 tail -f 和 ping 猜。先掂量一下,如果:你在找成熟稳定的大厂级产品——它还是 v0.0.x;你需要 stcp / xtcp——界面里已预留,但还没开放;你以为它帮你跑 frps——不是,frps 服务端必须你自己部署和维护(公网 IP、放行端口、token 都是你的事),否则面板里一个节点也连不上;Nodus 管的只是客户端这一侧;你依赖商业 SLA——它是一个个人维护的开源项目,反馈渠道是 issue。十二、写在最后回到开头那个场景:改一个端口,原来要 ssh、vim、重启、看日志四步。现在是打开面板,改,保存,它自己重载。Nodus 想做的事情,说白了就一句话:让内网穿透的管理回到"点几下鼠标"的正常水平。上游项目:podux(luckjiawei),Nodus 由它衍生而来项目地址:github.com/sexyfeifan/Nodus许可证:Apache 2.0,可以放心拿去自用、改、甚至集成进自己的工具链文档五篇,覆盖快速开始、迁移指南、配置说明、安装部署、API 与开发它现在还很小,star 也不多。但一个两天推了七个版本、把提权漏洞放在第三版就修掉、把"别把密钥打进日志"写进红线的项目,值得你花五分钟部署一个试试——前提还是那句:frps 得你自己先备好。有问题直接开 issue,我都在。附录:速查卡前提:先有 frps(不部署就用不了)TOML複製# frps.toml —— 跑在有公网 IP 的机器上 bindAddr = "0.0.0.0" bindPort = 7000 auth.token = "你的 token" # frps -c frps.toml,安全组放行 7000 及各代理端口这个 auth.token 就是面板"添加节点"时要填的那个。部署BASH複製bash scripts/setup.sh # 一键(MODE=docker|binary) docker run -d --name Nodus --restart unless-stopped \ -p 8090:8090 -v Nodus-data:/app/pb_data sexyfeifan/nodus:latest docker compose -f deploy/docker-compose.yml up -d ./Nodus serve --http 0.0.0.0:8090 # 二进制迁移BASH複製bash scripts/migrate-to-nodus.sh --dry-run # 先预览 bash scripts/migrate-to-nodus.sh # 再执行三个入口TEXT複製http://<服务器>:8090 用户端(自己创建的邮箱 + 密码) http://<服务器>:8090/_/ PocketBase Admin(超级管理员) frps 的 auth.token 添加节点时填,来自你的 frps 配置忘记密码:进 /_/,在 fh_users 集合中重置。
人在外面,想连回家里内网的某台机器。于是打开终端,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 集合中重置。