不少刚接触运维的朋友会遇到这样的需求:手里只有一台云服务器、一个公网IP,但手上可能有两三个甚至十几个域名,每个域名都要指向不同的网站。这时候nginx的多域名配置就派上用场了。其实原理很简单:浏览器发起请求时,会在HTTP头里带上Host字段,nginx根据这个Host值去匹配不同server块的server_name,从而把请求转发到对应的站点目录或后端服务。下面我们从头到尾把这个配置过程和容易踩的坑讲清楚。

一、基于域名的虚拟主机基本配置
nginx支持三种虚拟主机类型:基于IP、基于端口和基于域名。在只有一个IP的前提下,最常用的就是基于域名的虚拟主机。核心思路是在nginx配置中为每个域名单独写一个server块,每个server块用server_name区分,用root指定不同的站点目录。
下面是一个典型的配置示例,假设我们有两个域名site-a.com和site-b.com,都解析到同一台服务器:
# /etc/nginx/conf.d/multi-site.conf
server {
listen 80;
server_name site-a.com www.site-a.com;
root /var/www/site-a;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name site-b.com www.site-b.com;
root /var/www/site-b;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}两个server块都监听80端口,nginx收到请求后会根据请求头中的Host字段逐一匹配server_name,匹配到哪个server块就使用哪个配置。如果请求的Host值和所有server_name都不匹配,nginx会使用这个端口上的默认server,也就是配置文件中第一个出现的server块,或者显式标注default_server的那个。
这里有个细节值得注意:server_name可以同时写多个值,用空格分隔,比如主域名加www别名。如果域名比较多,也可以把每个域名的配置拆成独立的conf文件放在/etc/nginx/conf.d/目录下,nginx主配置文件里有一句include /etc/nginx/conf.d/*.conf;会自动加载它们,这样维护起来更清晰。
二、通配符、正则匹配与默认server的处理
server_name的写法比很多人想象的灵活。除了精确匹配,还支持前缀通配符、后缀通配符和正则表达式三种形式:
# 通配符:匹配所有子域名
server {
listen 80;
server_name *.ippipp.com;
root /var/www/wildcard;
}
# 后缀通配符:匹配 mail.www.ippipp.com 这类特殊写法
server {
listen 80;
server_name www.example.*;
}
# 正则匹配:以 ~ 开头,捕获主机名中的用户部分
server {
listen 80;
server_name ~^(www\.)?(.+)$;
root /var/www/sites/$2;
}匹配的优先级顺序是:精确匹配优先,其次是前缀通配符,再次是后缀通配符,最后才是正则匹配。也就是说,如果同时存在server_name ippipp.com和server_name *.com,访问ippipp.com时命中的是前者。理解这个优先级对排查“为什么请求进了错误的server块”非常有帮助。
另外强烈建议显式配置一个默认server,用来兜底处理那些不匹配任何域名的请求,比如直接用IP访问的情况。可以返回444状态码直接断开连接,避免别人把乱七八糟的域名解析到你的IP上蹭流量:
server {
listen 80 default_server;
server_name _;
return 444;
}这里的下划线只是一个无效域名的占位符,没有任何特殊含义,换成别的写不可能是域名的字符串也可以。返回444是nginx特有的行为,它不返回任何响应直接关闭连接,比返回403更省资源。
三、多域名HTTPS配置与证书问题
上了HTTPS之后,多域名配置会复杂一些,因为证书是绑定域名的。先说最基础的方案:每个域名一个server块,各自配置各自的证书:
server {
listen 443 ssl;
server_name site-a.com www.site-a.com;
ssl_certificate /etc/nginx/ssl/site-a.com.pem;
ssl_certificate_key /etc/nginx/ssl/site-a.com.key;
root /var/www/site-a;
}
server {
listen 443 ssl;
server_name site-b.com;
ssl_certificate /etc/nginx/ssl/site-b.com.pem;
ssl_certificate_key /etc/nginx/ssl/site-b.com.key;
root /var/www/site-b;
}这里的关键是SNI(Server Name Indication)机制。TLS握手时,浏览器会把要访问的域名放进ClientHello报文,nginx据此选择对应server块的证书。现代浏览器基本都支持SNI,所以每个server块使用不同证书完全没问题。
如果一个server块要承载多个域名且共用一张证书,可以申请多域名证书(SAN证书)或泛域名证书,把多个域名打包进一张证书,然后多个server_name共用同一组ssl_certificate配置。证书的SAN字段里包含哪些域名,哪些域名就可以安全地复用这张证书。对于子域名多的场景,一张*.ippipp.com的泛域名证书能省去不少续期管理的工作量。
四、常见问题与注意事项
1. 修改配置后忘记重载。改完配置文件必须执行nginx -t检查语法,通过后再执行nginx -s reload才会生效。很多人改完文件直接刷新浏览器发现没变化,以为配置写错了,其实只是没reload。
2. DNS解析没生效。域名必须先做A记录解析到服务器IP,可以用ping或者nslookup确认解析是否已经生效。DNS记录有缓存时间,刚添加的记录可能要等几分钟到几小时才能全球生效,这段时间配置再正确也访问不到。
3. 请求全部进了第一个server块。典型原因是域名没有正确匹配任何server_name,nginx按规则使用了默认server。检查server_name拼写、是否带了www、配置文件是否真的被include进来了。nginx -T命令可以输出最终合并后的完整配置,用来确认你的conf到底有没有被加载。
4. 防火墙和端口问题。多个站点如果还想监听其他端口,记得在防火墙和安全组里放行对应端口,云服务器尤其要注意控制台的安全组规则,只改系统防火墙是不够的。
5. 后端转发时的Host传递。如果server块里用的是proxy_pass转发到后端应用,默认情况下转发给后端的Host头会是proxy_pass中指定的地址,可能导致后端应用识别不到真实域名。这时需要加一行proxy_set_header Host $host;把原始域名传过去。
总结一下,nginx多域名配置的核心就是“一个server块对应一组域名”,靠server_name区分、靠SNI选证书、靠默认server兜底。把这几个概念理顺,再注意reload和DNS这些操作层面的细节,一台服务器跑多少个站点都不在话下。
nginx多域名配置server_name虚拟主机修改时间:2026-09-15 07:22:29