必须用~开头的正则匹配并配合(?1)命名捕获组才能提取子域名;通配符.example.com仅静态匹配,无法获取变量;提取的$subdomain可用于proxy_pass、root等指令。. ↩

要用 server_name 提取子域名,必须用正则表达式匹配,并配合命名捕获组。通配符(如 *.example.com)只能匹配,不能提取变量;真正能“拿到子域名”的只有带 (?<name>...)</name> 的正则写法。
必须用 ~ 开头启用正则匹配
Nginx 要识别正则,server_name 值必须以 ~(区分大小写)或 ~*(不区分)开头:
-
server_name ~^(?<subdomain>[^.]+)\.example\.com$;</subdomain>✅ 正确:启用正则并命名捕获 -
server_name *.example.com;❌ 无法提取$subdomain,仅静态匹配 -
server_name ~^([a-z0-9\-]+)\.example\.com$;⚠️ 可用,但只能用$1引用,不如命名清晰
命名捕获组语法要规范
捕获子域名最常用的是 (?<subdomain>[^.]+)</subdomain>,含义是:
-
[^.]+:匹配一个或多个非点号字符(即子域名本身,如api、shop) -
(?<subdomain>...)</subdomain>:把这部分内容存进变量$subdomain,后续可直接调用 - 注意转义点号:
\.,否则.会匹配任意字符 - 结尾加
$防止误匹配test.example.com.bad这类非法 Host
捕获的变量可在 proxy_pass 或 root 中直接使用
提取出来的 $subdomain 是 Nginx 内置变量,只要在同一个 server 块里,就能用于转发或路径定位:
- 反向代理场景:
proxy_pass https://$subdomain.backend.internal/; - 静态文件场景:
root /var/www/sites/$subdomain; - 透传给后端:
proxy_set_header X-Subdomain $subdomain;
别忘了兜底和测试
没有匹配上的请求会被交给第一个 server 块,容易出错:
- 加一个
default_server块拦截非法 Host:server { listen 80 default_server; server_name _; return 444; } - 每次改完配置,先运行
nginx -t检查语法,再nginx -s reload - 用
curl -H "Host: api.example.com" http://your-ip手动验证 Host 匹配是否生效











