nginx多域名配置的核心结论很简单:同一台服务器上,通过多条server指令,让不同域名各自匹配独立的配置块,就能实现多域名共存。这不是什么黑科技,而是nginx最基础的虚拟主机能力,但真正在实际项目里把它用顺,仍有一些值得注意的细节和场景化技巧。
先分清nginx多域名配置的三种可靠方案
很多新手第一次上手多域名,会把所有server块塞进同一个配置文件,这样虽然能跑,但后期维护成本很高,业内专家指出,多域名场景越复杂,越应该在配置结构上做拆分,以下是三种覆盖绝大多数场景的方案,按推荐程度排序。
多条server指令各管各的域名
这是最直观、也最不容易出错的方法,核心逻辑就是为每个域名写一个独立的server块,通过listen和server_name来区分请求该由谁处理。
server {
listen 80;
server_name a.example.com;
root /var/www/siteA;
index index.html;
}
server {
listen 80;
server_name b.example.com;
root /var/www/siteB;
index index.html;
}
这种写法的优势是隔离性强,你可以在某个server块里单独配置rewrite规则、location匹配、访问日志路径,完全不影响其他域名,如果某个域名的流量异常,可以快速定位到对应的配置段落。
正则与泛域名匹配收敛子域
当域名数量较多,比如有几十个二级子域名,且它们的处理逻辑完全一致时,逐条写server块就太啰嗦了,此时可以用正则匹配或泛域名解析来收敛配置。
server {
listen 80;
server_name ~^[a-z0-9]+.example.com$;
root /var/www/subdomains/$host;
}
这样所有符合规则的子域都会命中这个server块,$host变量可以让你在根目录上做动态映射,需要注意,正则匹配的方式不适用于差异很大的业务场景如果各个子域要跑的PHP版本或路由规则不同,老老实实用方案一反而更稳。
default_server兜底未匹配请求
当请求到了服务器,但nginx找不到匹配的server_name时,它会选择默认的server块来处理,未被显式匹配的域名、直接用IP访问的请求,都会走default_server。
server {
listen 80 default_server;
server_name _;
return 444;
}
这段配置的含义是:凡是没匹配到任何规则域名的请求,直接断开连接,对于不想被乱七八糟的域名指向过来的场景,这个配置非常有用,444状态码是nginx特有的,表示直接关闭连接,不返回任何响应。
nginx多域名配置的实操关键:从端口区分说起
多域名配置里最容易混淆的一点,是端口与域名的配合逻辑。
同端口绑多域:靠的是Host头而非端口
HTTP请求到达服务器时,nginx会读取请求头中的Host字段,然后与server_name做比对,多个域名完全可以共用一个80端口,不存在端口冲突的问题,这也是方案一能成立的基础。

但如果你希望不同域名访问不同的应用,比如A域名跑Nginx静态页面,B域名反向代理到后端Tomcat,那就要在server块里配不同的proxy_pass或root,而不是改listen端口。
nginx多域名映射不同端口的常见写法
有些场景下,你希望域名不变,但根据路径或子域访问不同端口上的服务,此时不用改nginx的listen,而是通过location或upstream做转发。
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name admin.example.com;
location / {
proxy_pass http://127.0.0.1:9090;
}
}
这种情况下,nginx多域名映射不同端口的本质,是基于域名的反向代理分发,当你需要两个web服务同时跑在同一台机器上时,这个写法比改端口监听更符合惯例,真实项目中,不少人会问“nginx多域名配置是一个端口还是多个端口”,答案很明确:统一走80或443入口,内部分发到各自端口。
多域名共配SSL:nginx多域名证书编排的两种思路
HTTPS已经成了标配,多域名配置里最麻烦的就是证书部分,2019年前后Let‘s Encrypt的普及让免费证书获取变得简单,但多域名的证书管理依然有取舍。
每个域名单独一套证书与配置
这种方式最直接,每个域名对应一个证书文件,各server块互不干扰,配置写法如下:
server {
listen 443 ssl;
server_name a.example.com;
ssl_certificate /etc/nginx/certs/a.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/a.example.com/privkey.pem;
}
server {
listen 443 ssl;
server_name b.example.com;
ssl_certificate /etc/nginx/certs/b.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/b.example.com/privkey.pem;
}
优点是隔离清晰,证书到期后可以单独续期,不影响其他域名,缺点是当域名数量增多时,证书文件的管理成本跟着上涨,服务器上要定期执行多个续期任务。
泛域名证书一劳永逸
如果你的所有域名都是同一个主域的二级子域,那直接申请一张泛域名证书(.example.com)是最省心的,整个nginx配置文件里,所有server块共用同一组证书路径,续期也只需针对这一张证书操作。
ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
泛域名证书不便宜,但覆盖面极广,如果你只有三五个域名且都是不同主域,那建议用思路一;如果你有几十个子域且都在同一个主域下,泛域名证书会让nginx多域名证书配置过程清爽很多。

多域名全上HTTPS之后:nginx多域名HSTS与HTTP跳转
当所有域名都配上SSL证书后,下一步就是安全增强和跳转优化,这里着重说两个最常见的落地配置。
HTTP强制跳转HTTPS
每个域名的80端口server块,可以直接返回301跳转到对应的HTTPS地址:
server {
listen 80;
server_name a.example.com b.example.com;
return 301 https://$host$request_uri;
}
上面的写法把两个域名合并到一个跳转server块里,减少了重复代码,用户输入a.example.com时,自动被带到https://a.example.com,路径参数完整保留。
HSTS头统一开启
开启HSTS后,浏览器会在一定时间内强制使用HTTPS访问该域名,不再先发起HTTP请求。
add_header Strict-Transport-Security "max-age=31536000" always;
可以把这行加在HTTPS server块的server层级,这样所有多域名下的子站都会继承,不需要逐个重复添加,注意HSTS一旦开启,浏览器就会强制HTTPS,如果你后续想关闭某个域名的HTTPS服务,需要先将max-age调小或移除响应头,等待过期后再调整,否则用户浏览器会拒绝明文连接。
nginx多域名配置后最常见的排错现场
配置写完了,nginx -t也通过了,但浏览器访问就是不对,多数情况下,问题不在nginx配置本身,而在以下几个容易被忽略的地方。
域名解析指向了错误的服务器IP
多域名配置的前提是DNS解析正确,如果你有两台服务器,A服务器配置了domainA,B服务器配置了domainB,但两个域名都解析到了A服务器,那请求永远不会到达B,排查时先ping一下域名,看返回的IP是否是对应服务器的公网地址。
同一个server块里写了多个互斥的root
有人为了省事,会把多个域名写在同一个server块里,靠if判断来切换root,这种做法容易出错:
server {
listen 80;
server_name a.example.com b.example.com;
root /var/www/$host;
}
这种写法依赖目录名与域名保持一致,如果目录没建好或大小写不一致,就会404,相比之下,还是用独立的server块更直观。
修改配置后没有reload
nginx的配置改动后需要执行nginx -s reload才会生效,不是改完文件就立即生效,很多人改了server_name忘了执行reload,测试时始终是旧配置在跑,写一个小脚本把这行命令固化下来,可以有效避免这个问题。
防火墙和安全组拦截了80或443端口
国内云服务器厂商通常有两层网络访问控制,一层是系统内部的firewalld或iptables,另一层是云控制台的“安全组”,即使nginx正常监听80端口,安全组没有放行80,外部也就无法访问,排查连接超时的问题时,先确认安全组是否放行了TCP端口,再去折腾nginx配置。

实际项目中的nginx多域名配置方案参考
具体到真实的上线场景,配置方案可以按服务器资源灵活调整。
如果是一台小型云服务器,跑的是个人博客加一个小型API服务,那这样的配置足够清晰:
- 博客域名 blog.example.com 指向静态目录
- API域名 api.example.com 反向代理到本机8080端口
- 管理后台域名 admin.example.com 用密码保护并限定IP访问
server {
listen 80;
server_name blog.example.com;
root /var/www/blog;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
server {
listen 80;
server_name admin.example.com;
allow 192.168.1.0/24;
deny all;
proxy_pass http://127.0.0.1:9090;
}
这个配置里,管理后台还加上了IP白名单限制,只有内网地址能访问,对外完全关闭,一张服务器同时承载三个域名的业务,nginx多域名配置让它们在逻辑上完全隔离,互不干扰。
常见问题:nginx多域名配置一站式解答
nginx多域名争用80端口,后面配置的域名会不会不生效?
不会,nginx监听80端口用的是同一个socket,多个server块会按照配置加载顺序和server_name匹配规则来分发请求,不存在第二个域名抢不到端口的问题,只要server_name与请求的Host头一致,且配置无语法错误,所有域名都会正常响应。
nginx配置多域名时,IP直接访问会命中哪个server块?
IP访问时没有Host头,或Host头是一个IP地址,nginx会将其交给default_server处理的server块,如果没有任何server块声明default_server,则使用server_name的第一个server块,所以建议显式指定一个default_server块做兜底,要么返回444,要么返回一个简单的提示页面。
每个域名都需要单独配置一个server块吗,能不能共用一套配置?
如果多个域名的处理逻辑完全相同,可以在一个server块里用空格分隔多个server_name,比如server_name a.example.com b.example.com c.example.com,这样配置会共用同一套root和location规则,请求来源域名可以通过$host变量在应用层区分,但一旦某个域名的行为开始分化,就应该把它拆到独立的server块中,避免复杂条件判断堆在一起,多域名配置的核心原则是简单、清晰、可维护,单块共用适合完全同质化的场景,独立server块适合业务差异化的场景,两者之间没有谁更好,只有谁更匹配你的实际部署。
nginx多域名这件事,本质上就是让一台服务器承载多个站点入口,把server块的配置逻辑理顺,把证书、跳转、安全头这些细节补齐,你就能在同一份nginx环境里管理好任意数量的域名站点,不焦虑端口冲突,也不怕配置海洋里迷路。
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/783388.html

