nginx配置多域名并不复杂,核心在于利用server块配合server_name指令实现域名分流,一个80端口即可承载多个网站,关键在于配置顺序与默认server的处理。
nginx一个服务器配置多个域名的核心逻辑
很多朋友第一次接触nginx多域名配置时,会下意识觉得需要多个端口或多个IP,实际上nginx的虚拟主机机制早就解决了这个问题,每个server块就是一个虚拟主机,nginx收到请求后,会根据请求头中的Host字段去匹配对应的server块,匹配规则简单粗暴:先精确匹配,再通配符匹配,最后正则匹配。
举个例子,你把blog.example.com和shop.example.com都解析到同一台服务器的同一个IP上,nginx收到访问blog.example.com的请求时,看到Host是blog.example.com,就会去server块里找server_name写了这个名字的那个配置,找到就进去执行,没找到?那就走进默认server,一般是第一个加载的或显式标记default_server的那个。
这里有个常见误解要澄清:server_name本身不解析域名,也不监听端口,它只是nginx做请求路由的一个标识,DNS解析发生在请求到达nginx之前,所以你得先把所有域名的A记录都指向服务器IP,这一步是前提。
server_name匹配规则的优先级
行业共识认为,server_name的匹配优先级从高到低依次是:
- 精确匹配,比如
server_name www.example.com; - 前通配符,比如
server_name .example.com; - 后通配符,比如
server_name www.; - 正则匹配,比如
server_name ~^www.d+.example.com$;
如果你的多个域名长得特别像,比如example.com和www.example.com,记得把精确匹配的写在前面,或者干脆用通配符server_name .example.com;一把梭,这个写法同时匹配裸域和www子域。
默认server的坑
很多人配置完nginx多域名后发现,访问域名A打开了域名B的站点,十有八九是默认server在捣鬼,当你用IP直接访问,或者Host头没匹配到任何server_name时,nginx会把请求交给默认server。建议单独创建一个默认server块,直接返回444状态码或跳转到你的主域名,避免别人用IP扫到你的其他站点。
server {
listen 80 default_server;
server_name _;
return 444;
}
这个return 444是nginx特有的,直接断开连接不返回任何响应,用来防扫描很顺手。
nginx配置多个域名共用80端口的实操步骤
假设你有一台服务器,要跑example.com和test.cn两个站点,两个都是纯静态页面,具体操作路径如下:

第一步:准备站点目录
mkdir -p /var/www/example.com mkdir -p /var/www/test.cn
把对应网站的静态文件放进去,目录权限记得设置好,nginx进程用户一般是www-data或nginx,确保有读取权限。
第二步:创建独立的配置文件
nginx的配置有个好习惯:一个站点一个conf文件,放在/etc/nginx/conf.d/目录下,主配置nginx.conf里用include /etc/nginx/conf.d/.conf;引入,这样后续维护时删改单个站点不会影响其他。
创建/etc/nginx/conf.d/example.com.conf:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}
再创建/etc/nginx/conf.d/test.cn.conf:
server {
listen 80;
server_name test.cn;
root /var/www/test.cn;
index index.html;
}
两个文件都监听80端口,但server_name不同,nginx完全可以区分。
第三步:检查语法并重载
这一步强烈建议养成肌肉记忆,每次改完配置都要跑一遍:
nginx -t systemctl reload nginx
nginx -t用来检查语法,出错的话它会明确告诉你哪个文件哪一行有问题,大概率是缺分号或花括号没闭合。语法检查通过后再reload,千万别直接restart,reload是平滑重载不会断连接,restart会有一瞬间的服务中断。
第四步:本地验证
用curl指定Host头模拟请求,不用等DNS生效就能测:
curl -H "Host: example.com" http://127.0.0.1 curl -H "Host: test.cn" http://127.0.0.1
返回不同页面内容就说明配置生效了。
动态域名与泛解析的配置技巧
如果域名数量特别多,比如user1.example.com、user2.example.com这种用户子域名场景,一个个写server块实在不优雅,nginx支持正则匹配server_name,配合$host变量可以做到动态路由。
server {
listen 80;
server_name ~^(?<subdomain>.+).example.com$;
root /var/www/$subdomain;
index index.html;
if (!-e $request_filename) {
rewrite ^ /index.html last;
}
}
这样只要目录存在,任何子域名都能直接对应到同名目录,但这招有个前提:DNS那边要用泛解析,把`

.example.com`的A记录也指到服务器IP上,另外正则server_name的优先级最低,跟其他精确域名混用时小心被抢走请求。
nginx多域名ssl证书怎么配置
2017年以后百度对HTTPS站点有收录倾斜,这个不用多说,多域名配HTTPS有两种路子:一个域名一个证书,或者一张多域名证书覆盖所有域名。
一个域名一个证书的写法
Let’s Encrypt的免费证书90天续期一次,配合certbot工具可以自动续期,配置示例:
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/example.com;
index index.html;
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
这里的第二个server块负责把HTTP流量301跳到HTTPS,注意跳转时要带上$request_uri,不然用户访问的具体页面路径会丢失,跳到首页算轻的,影响收录就麻烦了。
泛域名证书
如果你管着一大堆子域名,.example.com的泛域名证书比多域名证书性价比高得多,一张证书覆盖所有子域名,写法差别只在证书文件:
ssl_certificate /etc/nginx/ssl/example.com.pem; ssl_certificate_key /etc/nginx/ssl/example.com.key;
获得SSL证书之后配置多域名HTTPS,核心步骤其实就是改证书路径和监听443端口,逻辑跟80端口完全一致。
nginx配置域名后访问不了的排查路径
这个问题我看到过太多次了,十个里八个是防火墙或安全组没放行,按照下面顺序排查,多数情况下能快速定位。
检查端口监听状态
ss -tlnp | grep nginx
看nginx是否真的在监听80或443端口,如果输出里没有相关行,说明nginx没起来或配置有误,跑一下nginx -t看报错。
检查云服务器安全组
简米云、酷番云、华为云的服务器除了系统自带防火墙,还有一层安全组在云控制台里。安全组没放行80端口,外面无论如何都连不上,但你在服务器本机curl localhost却能通,这是最典型的症状。
检查系统防火墙
firewall-cmd --list-all # CentOS 7+ ufw status # Ubuntu
CentOS默认的firewalld或者Ubuntu的ufw,手动放行端口:
firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload

检查DNS解析
dig +short example.com nslookup example.com
看解析结果是否指向你服务器IP,如果域名是刚买的,DNS生效需要时间,国内云厂商的DNS一般几分钟到几小时。
nginx多域名配置的常见问题
多个域名指向同一个站点怎么处理
直接在server_name后面空格拼接:
server_name example.com example.net example.org;
别忘了加www开头的变体:server_name example.com www.example.com;。
主域名和子域名想用不同站点
主域名一个server块,子域名另一个server块,各自指向独立目录,这就是标准的nginx配置多域名虚拟主机思路。
域名后面带端口号访问
http://example.com:8080这种,需要在listen指令里指定端口:
server {
listen 8080;
server_name example.com;
}
或者用listen 80;支持默认端口访问,域名后面不用带端口,生产环境还是建议走80/443,8080这类端口容易被扫描器盯上。
多域名配置文件和apache的.htaccess有什么区别
nginx没有目录级配置文件,所有规则都集中在server块里,改完必须reload才生效,换nginx之后,原来apache的RewriteRule要改写成nginx的rewrite语法,伪静态规则迁移是最容易踩坑的点。
nginx多域名配置答疑
问:nginx配置多域名一定要买多域名SSL证书吗?
不一定,两个域名可以分别申请免费证书,各自配置独立的证书文件路径,一张多域名证书在证书管理上稍微省事,但续期、部署的复杂度跟多张证书差别不大,如果域名超过五个,用泛域名证书或通配符证书更划算。
问:nginx多域名配置教程里说改完配置要restart,但restart后服务真的会断吗?
会,restart会先停掉nginx进程再启动,这个过程中所有正在处理的请求都会断开,reload则是平滑重载,master进程重新加载配置,worker进程逐个替换,不影响正在进行的请求,所以线上环境改配置一律用reload,只有在nginx二进制升级或配置文件完全混乱时才考虑restart。
问:多个域名共用一个配置文件,还是分开写更好?
分开写,一个域名一个文件,文件名跟域名对应,比如example.com.conf,后面要找配置的时候一眼就能定位,所有域名挤在一个文件里,改一个站点的规则时容易手滑碰到别的配置,而且nginx读取配置文件是按顺序加载的,后面万一有语法错误,可能牵连整个文件里的站点全部挂掉。
