Nginx多域名配置无效子域名catch-all块报重复default_server错误
问题根因
两个异常的核心触发原因:
- 重复default_server启动报错:Nginx同一监听端口(含对应IPv4/IPv6地址)全局仅允许定义一个default_server块,你在domain1、domain2的配置中各声明了一个443端口的default_server,必然触发重复定义错误。
- 移除default_server后的重定向死循环:这里有两个问题,一是你写的
_.domain1.com是无效匹配规则——Nginx的域名通配符仅支持放在域名最前或最后位置,_本身是无意义的占位符而非通配符,放在域名中间完全无法匹配预期的子域名;二是Nginx的server块匹配优先级为「精确server_name匹配 > 前置通配符匹配 > 后置通配符匹配 > 正则匹配 > 对应端口第一个加载的server块」,无效子域名请求匹配不到任何有效规则时,会命中第一个加载的443 server块(也就是裸域跳www的规则),该规则会给当前$host前缀加www后跳转,下一次请求依然匹配不到有效规则,会持续给域名前缀叠加www,最终形成死循环。
另外你贴的原始配置里还有几处语法笔误,包括server_name行末尾缺失分号、[::]443缺失冒号、server_name:多写了冒号,这些也会导致配置加载失败,修复时需要一并修正。
修复步骤
1. 配置全局兜底default_server
删除所有域名独立配置中带default_server标记的catch-all块,在主配置文件(即你原来的default.conf)所有域名配置include语句的最前面,添加全局唯一的80、443端口兜底server块,拦截所有完全不匹配已配置域名的请求:
# 80端口全局兜底 server { listen 80 default_server; listen [::]:80 default_server; server_name _; return 404; } # 443端口全局兜底 server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; server_name _; # 替换为机器上任意一份有效SSL证书路径即可,仅用于完成SSL握手 ssl_certificate /path/to/any/valid/fullchain.pem; ssl_certificate_key /path/to/any/valid/privkey.pem; return 404; }
2. 修正单域名的无效子域名拦截规则
对每个域名的独立配置文件做两处调整:
- 修正通配符规则:将原来无效的
_.domain.com写法替换为正确的前置通配符*.domain.com,通配符块不要加default_server标记 - 调整块顺序:将子域名拦截的通配符块放在该域名所有443端口server块的最末尾,利用Nginx最长匹配优先级规则,保证只有未单独配置的子域名才会命中该拦截块
以domain1.conf为例,修正后配置如下:
# HTTP统一跳HTTPS server { listen 80; listen [::]:80; server_name domain1.com www.domain1.com; return 301 https://$host$request_uri; } # 裸域跳www server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name domain1.com; include /path/to/ssl_config.conf; return 301 https://www.$host$request_uri; } # 正常提供服务的www子域名 server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.domain1.com; include /path/to/ssl_config.conf; location / { proxy_pass http://$app; } } # 拦截该域名下所有未单独配置的子域名 server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name *.domain1.com; include /path/to/ssl_config.conf; return 404; }
domain2.conf按完全相同的逻辑调整,替换对应域名为domain2.com即可。
3. 校验并重载配置
执行配置语法校验:
nginx -t
确认输出syntax is okay、test is successful后,重载Nginx使配置生效:
nginx -s reload
修复逻辑说明
- 全局仅保留一份default_server配置,从根源解决重复default_server的启动报错,所有指向你服务器IP但未在Nginx中配置的域名请求,都会被全局兜底块直接拦截返回404。
- 单域名下的
*.domain.com通配符块放在同域名所有精确匹配规则之后,优先级低于精确配置的裸域、www子域名规则,只会命中foo.domain1.com这类未单独配置的子域名,不会干扰正常业务的跳转逻辑,彻底解决重定向死循环问题。
内容的提问来源于stack exchange,提问作者lonix
相关产品推荐
相关产品推荐

