它是什么
家里没有公网 IP,运营商也不给,但 Navidrome、PhotoPrism、Memos、Homer 这些服务我希望在外面也能随手打开。这个项目就是用 frp 在中间加一跳 VPS,把内网服务映射到公网域名上:VPS 跑 frps,家里那台 Debian 13 的 xiejun-web(192.168.50.164)跑 frpc,配置文件分别放在 projects/vps/frp/frps.toml 和 acme-frpc.toml。另外还挂了一个 SakuraFrp 的容器 natfrp-service,作为备用通道。
为什么这么做
直接在路由器上做端口映射,一是没有公网 IP,二是把服务裸露在公网上不太放心。frp 的好处是入站流量只从 VPS 的一个端口进来,家里这边是主动往外连,NAT 和动态 IP 都不影响。前面再套一层 Nginx Proxy Manager 做域名路由和证书,外部只需要认域名,不关心后面是哪个容器、哪个端口。
现在的状态
运行中,日常在用。HTTP 类服务走域名直连;Minecraft 基岩版那边是 19132/udp,不是 Java 版的 25565,映射时协议要选对。Windows 那台(192.168.50.155)目前只走局域网,Tailscale 网卡还没加入 tailnet,暂时不参与这条隧道。
功能
- VPS 自建 frps + 家里 frpc,绕过无公网 IP 的限制
- 用 NPM 统一做域名路由和证书,后端容器端口不外露
- acme 配置独立维护(acme-frpc.toml),证书走 SNI 区分域名
- SakuraFrp(natfrp-service 容器)作为备用隧道通道
- 覆盖 HTTP 与 UDP 服务,Minecraft 基岩版 19132/udp 也在范围内
技术栈
使用 / 部署教程
部署步骤
1. VPS 上装 frps
从 frp release 拉对应架构的包,写好 frps.toml:bindPort 是 frpc 连进来的端口,auth.token 自己生成一串长随机值。需要按域名分流的话再开 vhostHTTPPort / vhostHTTPSPort。用 systemd 托管,开机自启。
2. 家里跑 frpc
在 xiejun-web 上放 acme-frpc.toml:serverAddr 填 VPS,auth.token 与 frps 一致。每个服务写一段 proxy,localIP 填 192.168.50.164,localPort 指向 NPM 的 80/443,或者直接指向容器端口。
3. 证书
用 acme 在 VPS 侧签发,走 TLS-ALPN 或 DNS 方式都行,证书挂到 frps 的 vhostHTTPSPort 上。多个域名靠 SNI 区分,不需要给每个域名开独立端口。
4. Nginx Proxy Manager 里加规则
进 NPM 面板加 Proxy Host:域名 → 容器名加端口,例如 navidrome、photoprism、memos 各一条,勾上 SSL 并强制 HTTPS。这样隧道只需要一条到 NPM,新增服务只改 NPM,不动 frp 配置。
5. 验证
先用 curl -I https://你的域名 看返回头,再从外网(手机 4G)实际打开一次。用 systemctl status frpc 或 docker logs natfrp-service 看连接是否稳定,掉线先查 token 和 VPS 安全组。
6. 注意事项
- Minecraft 基岩版是
19132/udp,frp 的 proxy 类型要选 udp,端口别写成 25565。 - 自建 frp 和 SakuraFrp 两条通道不要映射同一个域名,会打架。
- 家里侧只需出站,别为了省事又去路由器开端口。
注意
frps.toml与 frpc 配置里含 auth token,不要提交到公开仓库;VPS 安全组只放必要端口。- Minecraft 基岩版走
19132/udp,与 Java 版的 25565 不是一回事,映射时协议和端口都要对。 - 自建 frp 与 SakuraFrp 容器是双通道,注意带宽限速与隧道冲突,排查问题时先确认走的是哪一条。