跟到了这里,说明你已经有一台能跑的 VPS 了——Nginx 在跑,SSL 配好了,浏览器访问https://你的域名能看到自己的网页。
一台 VPS 只跑一个网站,有点浪费。这篇讲怎么把利用率拉满——用 Nginx 反向代理,一台 VPS 同时跑多个网站、多个后端服务。
这不是入门内容了。前面的文章我尽量一步步走,今天这篇默认你已经会基本操作,已经弄好了前面的所有内容,直接上干货。
反向代理是什么
你用代理软件上网的时候用的是正向代理——你的请求先发给代理,代理帮你去访问目标网站。代理代理的是你。
反向代理反过来了——用户访问你的域名,请求先到 Nginx,Nginx 根据域名把请求转发到后面真正跑着的服务。用户不知道后面跑的是什么,只跟 Nginx 打交道。代理代理的是你的服务端。
为什么要加这一层?因为有了 Nginx 站在前面,你可以让不同域名走不同服务,让 Nginx 统一处理 HTTPS,让后端服务不用管证书。一台 VPS 就能同时伺候多个站点。
多个静态网站
你有两个域名:blog.example.com和portfolio.example.com,都解析到同一台 VPS。Nginx 靠server_name区分请求来自哪个域名,分发到不同目录。
比如访问阿伟的alois.bond是看到的阿伟的博客网站,然后xxx.xx同样指向这台vps,但是是指向我自己的节点管理后台
建目录放文件:
sudomkdir-p/var/www/blog /var/www/portfolioecho"<h1>My Blog</h1>"|sudotee/var/www/blog/index.htmlecho"<h1>My Portfolio</h1>"|sudotee/var/www/portfolio/index.htmlsudochown-R$USER:$USER/var/www/blog /var/www/portfolio写两个 Nginx 配置:
sudonano/etc/nginx/sites-available/blogserver { listen 80; server_name blog.example.com; root /var/www/blog; index index.html; location / { try_files $uri $uri/ =404; } }sudonano/etc/nginx/sites-available/portfolioserver { listen 80; server_name portfolio.example.com; root /var/www/portfolio; index index.html; location / { try_files $uri $uri/ =404; } }启用、reload、上 HTTPS:
sudoln-s/etc/nginx/sites-available/blog /etc/nginx/sites-enabled/sudoln-s/etc/nginx/sites-available/portfolio /etc/nginx/sites-enabled/sudonginx-t&&sudosystemctl reload nginxsudocertbot--nginx-dblog.example.com-dportfolio.example.com两个域名,两个网站,一台 VPS。HTTPS 一条命令全搞定。
代理后端服务
静态网站只是热身。反向代理真正的价值在于:把浏览器请求转发到 VPS 本机跑的各种服务。
比如你在 VPS 上跑了一个 Node.js API,监听 3000 端口。防火墙没开 3000 端口,用户直接访问不了。但可以通过 Nginx 代理——用户访问api.example.com的 80/443 端口,Nginx 帮你转发到localhost:3000。
配置长这样:
server { listen 80; server_name api.example.com; location / { proxy_pass http://localhost: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; } }和静态站点的区别就一点:没有root和index,换成proxy_pass把请求转发到localhost:3000。
下面几行proxy_set_header是把用户的真实 IP 和协议信息传给后端。否则后端只能看到请求来自 127.0.0.1,拿不到用户真实 IP——你的日志和风控就废了。
Python Flask(5000 端口)、Go 服务(8080 端口)、Java Spring Boot(8080 端口),换一下proxy_pass的端口就行,配置模式完全一样。
然后照常certbot --nginx -d api.example.com上 HTTPS。用户访问https://api.example.com,Nginx 解密 SSL,转发到localhost:3000(HTTP)。后端服务不用管证书——这叫SSL 卸载,Nginx 扛了加密的活,后端轻装上阵。
Docker 场景
如果你的服务用 Docker 跑,模式不变。
最简单的情况——Docker 容器映射端口到本机:
dockerrun-d-p8080:80--namemyapp nginxNginx 照常proxy_pass http://localhost:8080,和代理非 Docker 服务没区别。
多容器互相通信的场景,用 Docker Compose 把 Nginx 和应用容器放同一个 compose 网络里,通过容器名互相访问。这块展开是另一个话题了,但核心思路一样:Nginx 站在前面,按域名分发请求到后面的服务。
踩坑速查
502 Bad Gateway——Nginx 连不上后端服务。先查后端在不在跑:sudo ss -tlnp | grep :3000,没输出就是没启动。再查proxy_pass的端口和实际服务端口对不对。
端口被占用——Nginx 启动报bind() to 0.0.0.0:80 failed (98: Address already in use)。sudo ss -tlnp | grep :80看谁占了 80 端口,通常是 Apache,sudo systemctl stop apache2停掉。
证书不覆盖——给blog.example.com申请了证书,访问api.example.com报证书错误。申请时把所有域名列上:sudo certbot --nginx -d blog.example.com -d api.example.com -d portfolio.example.com。
改了配置不生效——sudo nginx -t测语法,sudo systemctl reload nginx重新加载。用reload不要用restart,reload 不中断现有连接。
你现在的架构
跟完整篇,你的 VPS 长这样:
Internet | ┌──────┴──────┐ │ Nginx │ ← 80/443,处理所有请求 │ (反向代理) │ SSL 在这里卸载 └──────┬──────┘ │ ┌──────────────┼──────────────┐ │ │ │ ┌──────┴──────┐ ┌────┴────┐ ┌───────┴───────┐ │ /var/www/ │ │ Node.js │ │ Python Flask │ │ blog/ │ │ :3000 │ │ :5000 │ └─────────────┘ └─────────┘ └───────────────┘对外只开 80 和 443,不同域名走不同站点或服务,SSL 统一在 Nginx 层处理,后端服务跑 HTTP 就行。一台 VPS 的资源被充分利用。
到头了
到这里,基础设施部分就结束了。你走过的路:
域名基础 → 注册域名 → VPS 基础 → 选购 VPS → 安全加固 → DNS 解析 → 建站上线 → 多站点部署。
你拥有了:一个自己的域名、一台配置好的 VPS、一个 HTTPS 网站、一台 VPS 跑多个服务的能力。
但这只是地基。后面还有 AI 实战篇——在 VPS 上部署 AI 对话、搭建私有知识库、统一管理 API 接口。地基打好,上面盖什么都行,后话咱们再聊。