Skip to content
VDS · 网站与 Web 服务器

反向代理:一个地址上的多个应用

如何按域名和路径让多个应用共用一个 VDS 公网地址、正确传递请求头,并且不破坏 WebSocket。

更新于 2026年8月23日

一台机器只有一个公网 IPv4 地址,但通常要运行多个应用。反向代理会接收 80 和 443 端口上的所有请求,并按域名或路径转发到内部服务。它还统一持有证书和共享日志。

布局

每个应用监听各自的本地端口,并且只监听 127.0.0.1:

  • 前端站点 — 127.0.0.1:3000;
  • API — 127.0.0.1:8000;
  • 监控面板 — 127.0.0.1:9090。

只有 Nginx 对外暴露。要检查某个应用是否被直接暴露:

ss -tulpn | grep LISTEN

像 0.0.0.0:3000 这样的行表示该服务可以从互联网访问,绕过代理且没有加密。

按域名

server {
    listen 80;
    server_name app.example.ru;
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name api.example.ru;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

如果没有 X-Forwarded-For,应用会把所有请求都看作来自 127.0.0.1,任何基于 IP 的限制都会失效。

按路径

location /api/ {
    proxy_pass http://127.0.0.1:8000/;
}

这里 proxy_pass 末尾的斜杠很关键:带上它,/api 前缀会被去掉,应用收到的是 /users;不带它,应用收到的是 /api/users。代理上有一半的“莫名其妙的 404”正是由此而来。

WebSocket 与长响应

location /ws/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

如果没有 Upgrade/Connection 这一对头部,连接会在握手后立刻断开;如果不延长超时时间,连接会在静默一分钟后断开。

常见错误

现象原因
502 Bad Gateway应用没有运行,或监听的端口不同
504 Gateway Time-out应用的响应时间超过了 proxy_read_timeout
无限重定向应用不知道 HTTPS — 请传递 X-Forwarded-Proto
文件上传失败client_max_body_size 太小;默认值为 1 MB
应用日志中都是同一个 IP没有传递 X-Forwarded-For

接下来:多站点、证书、Caddy 自动 HTTPS。

代理上的一个证书即可覆盖其后的所有应用。通过 127.0.0.1 的内部连接不需要加密 — 它们永远不会离开这台机器。