把十几个服务塞进一台公网 VPS,靠的不是某个框架,而是几条约定。对外只有 443,端口是内部的事。

一个域名、一堆端口

公网这台只暴露必要的东西:

端口 谁 说明
443 nginx 全部站点。TLS 终点,按子域名分流
80 nginx 只做 http→https 跳转和 ACME 证书校验,不出内容
22 sshd 管理入口
7000 frps 内网机器连进来的控制通道
7500 frps 面板 只看本机回环,不对公网
5001–5008 frps 隧道 后端端口,正常访问应该经过 443 反代,不建议直接对外
8081 docker-proxy OpenWebUI,只绑内网地址

看现场永远从这条命令开始:

1
ss -ltnp

它一行行告诉你「谁在听哪个端口」,比任何文档都准。端口冲突、容器反复重启、隧道没生效,都能从这行输出里看出来。

frp:让内网的服务有公网入口

方向很重要:是内网那台主动连出来,不是公网往里打。所以家里那台机器不需要公网 IP、不需要开端口、路由器不用做映射,拔了网线换到别的地方,只要还能上网,隧道自己就回来了。

配置分成两边:frps.toml 在公网(控制端口、面板、token 认证),frpc.toml 在内网(每个服务的 localIP / localPort / remotePort)。新增一个服务 = 在 frpc 里加一段 proxy、重启 frpc、在公网验证端口通。

一条验证命令够用:

1
curl -sI http://127.0.0.1:<remotePort>/

注意:frps.toml 里有 token,frpc.toml 里有同一个 token。这类文件不该进 git,也不该贴进任何文档——这篇文章里出现的所有配置都去掉了值。

跳板与 Minecraft · :5005 / :5006(不走 https)

5005 是把内网那台机器的 sshd 穿出来,用来远程维护;5006 通向另一台 Ubuntu,Minecraft 跑在那里(游戏端口另外转发)。

一台跳板、一台游戏机、一台公网入口——分开的好处是,某一台要重启或换系统时,其余的不受影响。

状态页

原来 80 端口上那张页就是干这个的:每 60 秒探测一次各个服务,用一个小圆点表示「此刻是否应答」,旁边标响应耗时。

它是个很好的习惯,因为它把「服务挂了」这件事从「用户来告诉你」变成「你自己看见」。现在这张页让位给了博客,文件还在 /var/www/home,随时可以挪回去。

几条硬规矩

  1. 容器不直接对公网,一律绑内网地址,前面走 nginx 或隧道。
  2. **改 nginx 之前先 nginx -t**,再 reload;两个 default_server 会让整个配置加载失败。
  3. 80 端口只有一个主人,新站点上线前先看 sites-enabled。
  4. 配置改动先备份,cp -a 三秒钟的事。