多个域名指向同一台机器、由同一个 Nginx 接流量时,设置方式是给每个域名一个 server 块,用 server_name 精确匹配请求头里的 Host,各自 proxy_pass 到对应后端。80/443 端口只监听一次,靠域名分流,不靠端口分流。动手前先确认两件事:这些域名的 DNS 已指向这台机器,且每个 server_name 在本机配置里只出现一次。
判断方向:多域名反向代理靠 server 块加 server_name 匹配,不是把多个 proxy_pass 堆进一个 server 里。适用场景是域名都解析到同一 IP、共用 80/443。操作前先 nginx -T 确认没有重复 server_name、没有意外的 default_server;改完 nginx -t 通过再 reload。验证用 curl 带 Host 头打 127.0.0.1,看落到哪个后端。风险边界:server_name 写错或漏配会静默落到 default_server,返回别的站点内容且不报错。
反向代理多个域名:先把能核对的事实摆清楚
先把手头能核对的东西列出来,再谈配置怎么写。
- 对象:同一台 Nginx 上要接的域名(如 a.example.com、b.example.com)、每个域名对应的后端地址和端口、配置文件位置。位置不要靠猜,用
nginx -V 2>&1 | tr ' ' '\n' | grep conf-path看--conf-path,再看 nginx.conf 里 include 指向哪个目录,Debian/Ubuntu 常见 sites-enabled,RHEL 系和容器镜像常见 conf.d。 - 前提:域名解析已指向本机地址,80 或 443 端口在防火墙与安全组放通,后端服务在本机或内网可达并正在监听。
- 可核对的现象:
nginx -T打印合并后的完整配置;nginx -t给出语法检查结果;/var/log/nginx/access.log与/var/log/nginx/error.log记录请求和错误;curl 带 Host 头请求 127.0.0.1 能看到实际由哪个后端响应。默认 combined 日志格式里没有 $host,想按域名分日志得自己定义 log_format,这一条很容易被忽略。
这几项都在手上再往下走:能打印当前配置、能改文件、能 reload、能看到日志。少一样就先补,不要靠试。
反向代理多个域名最容易搞错的一点
最常见的误解是把多个域名的 proxy_pass 写进同一个 server 块,或者以为 listen 80 后面并列写几个 server_name 就能自动分流。Nginx 的分流依据是请求头 Host 与 server_name 的匹配结果,一个 server 块只有一组 location 和 proxy_pass,装不下两套互不相同的后端。
判断分界在这里:Host 精确匹配到哪个 server_name,就走哪个 server 块;一个都没匹配上,就走标了 default_server 的那个 listen(没标则走该端口上第一个 server 块),而且整个过程不报错、日志里也看不出异常。
能把两种情况区分开的检查动作:

curl -I -H "Host: b.example.com" http://127.0.0.1/
nginx -T | grep -n "server_name\|listen"
返回的是 a 站点页面或 a 后端特有的响应头,说明 b.example.com 没匹配上、落到了 default_server;返回 b 后端的内容,说明 server_name 生效。这个动作比盯着配置文件一行行看更快得出判断。
反向代理多个域名:一个照着就能做完的做法
按下面顺序做,每步都写了该看到什么。
- 确认配置入口并备份:
该看到nginx -V 2>&1 | tr ' ' '\n' | grep conf-path ls /etc/nginx/conf.d/ /etc/nginx/sites-enabled/ 2>/dev/null cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak--conf-path指向的 nginx.conf,以及 include 引入的目录。 - 新建一个独立文件,两个域名写两份 server 块:
替换项只有域名、后端地址端口、日志路径。log_format 只能定义在 http 块,conf.d 里的文件通常已被 include 进 http 块;若报 duplicate log_format,说明已有同名定义,换个名字即可。除非确实想要一个兜底站点,否则不要在别的 server 块里补 listen 80 default_server。# /etc/nginx/conf.d/multi-domain.conf log_format by_host '$host $remote_addr [$time_local] "$request" $status'; upstream app_a { server 127.0.0.1:8081; } upstream app_b { server 127.0.0.1:8082; } server { listen 80; server_name a.example.com; access_log /var/log/nginx/a.access.log by_host; location / { proxy_pass http://app_a; 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 b.example.com; access_log /var/log/nginx/b.access.log by_host; location / { proxy_pass http://app_b; 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; } } - 检查再生效:
nginx -t 该看到 syntax is ok 和 test is successful;reload 没有输出一般就是接受了。有报错就别 reload,按提示的文件行号改。nginx -t nginx -s reload - 要走 HTTPS 的域名各自配证书:443 的 server 块同样按域名分开写,每个 server 块里的 ssl_certificate 和 ssl_certificate_key 指向该域名自己的证书,不要一份证书套所有域名。HTTP/2 的写法随版本不同,先用
nginx -v确认版本,再决定是 listen 443 ssl; 加 http2 on; 还是旧写法 listen 443 ssl http2;。
反向代理多个域名:怎么验证结果对不对
分三层验,别只看浏览器能不能打开。
- 配置层:
nginx -T | grep -n "server_name",每个域名应只出现一次,且没有两个 server 块抢同一个 server_name。 - 路由层:
正常结果:两次响应能看出不同后端的特征,比如不同的自定义响应头、不同页面标题或不同的跳转地址,状态码是后端真实返回的,不是 502 或 504。出现 502 说明 server_name 匹配对了但后端连不上,去 error.log 找 connect() failed 那行。curl -I -H "Host: a.example.com" http://127.0.0.1/ curl -I -H "Host: b.example.com" http://127.0.0.1/ curl -s -o /dev/null -w '%{http_code}\n' -H "Host: b.example.com" http://127.0.0.1/some-path - 日志层:
tail -f /var/log/nginx/a.access.log,另一台机器正常访问 a.example.com,该看到首列 $host 是 a.example.com;访问 b.example.com 时只应写进 b.access.log。两个域名的请求混进同一个文件,就是没匹配上,或日志指令写在了被继承的层级。
最后从外部再验一次:curl -I http://a.example.com 与 curl -I http://b.example.com,结果应与本机带 Host 头一致。不一致时先 dig +short a.example.com 看解析是否已生效,DNS 没切换时请求根本到不了这台机器,此时改配置是白费功夫。