Nginx 反向代理入门:让一台服务器跑多个网站
一台云服务器只有一个公网 IP、80 和 443 端口却要跑多个网站时,最直接的办法不是给每个网站各开一个端口,而是让 Nginx 站在前面做反向代理:浏览器先访问 Nginx,Nginx 再按域名把请求转发给本机不同端口、甚至不同目录的后端。这样对外只暴露 80/443,后端可以随便换端口、重启、扩容,用户感知不到。
一、安装并确认 Nginx 能跑起来
以 Ubuntu/Debian 为例:
sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx
nginx -v
sudo systemctl status nginx
安装完成后先在浏览器访问服务器 IP,能看到 Nginx 欢迎页说明服务已起。如果访问不通,先看两层放行:云服务器安全组放行 80/TCP(用 HTTPS 再放行 443/TCP),服务器本机防火墙也要放行,例如 sudo ufw allow 'Nginx Full'。不要一上来就改配置,先确认默认页能打开。
二、先理解 server 块:域名是分流的钥匙
Nginx 靠 server_name 区分网站。一个最简单的静态站点 server 块长这样:
server {
listen 80;
server_name www.example.com;
root /var/www/example;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
listen 是监听端口,server_name 是域名,root 是网站文件目录,location / 决定这个路径怎么处理。反向代理就是把 location 里的 root 换成 proxy_pass:不再读本地文件,而是把请求转给后端。
三、一个能用的反向代理配置
假设本机跑了两个后端:博客在 3000 端口,API 在 8000 端口。把配置写进 /etc/nginx/conf.d/sites.conf(或 sites-available 后做软链接到 sites-enabled,两种方式选一种,不要两处重复写同一个域名):
server {
listen 80;
server_name blog.example.com;
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.com;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
}
这几行 proxy_set_header 很重要,不能省。Host 让后端知道用户访问的是哪个域名;X-Real-IP 和 X-Forwarded-For 让后端日志和限流看到真实访客 IP,而不是永远的 127.0.0.1;X-Forwarded-Proto 让后端知道原始请求是 http 还是 https,避免生成错误的跳转链接。
注意 proxy_pass 末尾斜杠的区别:proxy_pass http://127.0.0.1:3000; 会把完整路径原样转发;proxy_pass http://127.0.0.1:3000/; 则会把 location 匹配到的前缀替换掉。只在明确需要改路径时才加斜杠,平时先用不带斜杠的写法。
四、多站点按域名分流:关键在 DNS 和 server_name
- 把
blog.example.com和api.example.com的 DNS A 记录都指向同一台服务器的公网 IP。 - Nginx 里分别为每个域名写一个
server块,server_name写准确,不要写成localhost或_。 - 可以再写一个默认 server 块,拦截没有匹配域名的直接 IP 访问,避免陌生域名解析到这台机器后看到别人的站点:
server {
listen 80 default_server;
server_name _;
return 444;
}
五、改完配置必须先测试再重载
每次改完都按这个顺序做,不要直接重启:
sudo nginx -t
sudo systemctl reload nginx
curl -I http://blog.example.com/
curl -I http://api.example.com/
nginx -t 通过才会输出 syntax is ok 和 test is successful,不通过时 reload 不会生效,要先按报错行号改配置。reload 是平滑重载,不会断开已有连接;只有 Nginx 本身升级或主进程异常时才需要 restart。
六、常见 502 Bad Gateway 排查清单
反向代理新手最常遇到 502,按这个顺序查,基本都能定位:
- 后端真的在跑吗?
ss -tlnp | grep 3000或curl http://127.0.0.1:3000/,先在服务器本机确认后端端口能通,再谈 Nginx。 - 端口写错了吗?对照后端实际监听端口和
proxy_pass里的端口,3000 写成 3001 就会 502。 - 后端只监听了 127.0.0.1 还是 0.0.0.0?反向代理走本机回环时用 127.0.0.1 就够,但如果后端在另一台机器,要写那台机器的内网 IP,并放行对应端口。
- 看 Nginx 错误日志,不要只看浏览器:
sudo tail -n 50 /var/log/nginx/error.log,里面会明确写是connection refused(后端没起)、timeout(后端太慢或防火墙拦截)还是no live upstreams。 - 超时问题:后端接口本来就慢时,适当放宽
proxy_connect_timeout 5s;、proxy_read_timeout 60s;,而不是无限调大掩盖慢接口。 - WebSocket 或长连接场景:除了上面几行,还要加
proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection "upgrade";,否则握手会失败。
七、总结
反向代理的核心就三步:Nginx 监听 80/443 对外;server_name 按域名分流;location 里用 proxy_pass 转给后端并带上真实请求头。把这套流程跑通后,再给每个域名配 HTTPS(listen 443 ssl; 加证书路径),一台服务器跑五六个小网站也完全够用。记住一条铁律:改配置先 nginx -t,再 reload,出问题先看 error.log,不要凭感觉反复重启。
- 点赞
- 收藏
- 关注作者
评论(0)