Ubuntu 20.10下NGINX多租户配置:通配子域SSL、多根域及自定义域名映射咨询
无限制子域访问不生效的排查与修复
常见配置疏漏(子域不生效的核心原因)
- 未配置泛域名DNS解析:NGINX侧配置了
*.mydomain.com匹配规则,但域名服务商后台未添加主机记录为*的A/AAAA解析指向服务器公网IP,所有子域请求根本无法抵达NGINX,这是最高发的疏漏点 - 通配符证书申请不完整:通配符证书必须通过DNS验证模式签发,若使用普通HTTP验证流程,实际生成的仅为根域单域名证书,不覆盖任意子域的HTTPS请求
- 旧配置优先级冲突:未清理旧的单租户server块,残留的
default_server规则会拦截所有未明确匹配的子域请求,导致泛匹配规则失效
可落地的正确配置
保留原有单租户块的安全头、PHP解析、静态文件规则,仅调整核心监听与域名匹配部分,配置如下:
# 80端口块:负责HTTP请求跳转、证书验证 server { listen 80 default_server; listen [::]:80 default_server; server_name mydomain.com *.mydomain.com; # 放开Let's Encrypt证书验证路径 location ~ /.well-known/acme-challenge/ { root /var/www/html; } # 全量请求跳转HTTPS location / { return 301 https://$host$request_uri; } } # 443端口块:负责核心业务处理 server { listen 443 ssl default_server; listen [::]:443 ssl default_server; http2 on; # 通配符证书路径(certbot生成后自动写入) ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # 同时匹配根域与所有泛子域 server_name mydomain.com *.mydomain.com; # 沿用原有单租户配置逻辑 root /var/www/html/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.php index.html index.htm index.nginx-debian.html; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.0-fpm.sock; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } }
落地操作步骤
- 登录域名服务商后台,添加泛解析记录:主机记录填
*,记录类型选A,值填服务器公网IP,TTL保持默认值 - 申请通配符证书时手动指定DNS验证模式,执行命令
certbot certonly --nginx -d mydomain.com -d *.mydomain.com --preferred-challenges dns,按照提示添加临时TXT记录完成域名所有权验证 - 执行
nginx -t校验配置语法,无报错后执行systemctl reload nginx重载服务 - 验证泛匹配生效:用命令
curl -H "Host: test.mydomain.com" http://<服务器公网IP>测试,返回200状态码即代表配置生效
自定义域名映射租户子域的实现方案
不需要为每个用户自定义域名单独编写server块,通过默认泛匹配+后端Host头识别的逻辑,可实现无上限的自定义域名接入:
配置调整点
- 保持上述HTTPS与HTTP块的
default_server属性,所有未匹配专属证书的域名请求,会自动落到该通用块内处理 - 保留通配符证书作为默认证书,用户侧仅需将自定义域名通过CNAME记录指向
mydomain.com,请求抵达后由后端PHP应用判断当前请求的Host头,匹配对应的租户上下文即可 - 动态匹配自定义域名证书,避免硬编码维护:在NGINX的http全局配置段新增map规则,自动根据请求Host匹配对应证书路径
将443块内原来硬编码的证书路径,替换为变量# 公钥路径映射 map $host $ssl_cert_file { default /etc/letsencrypt/live/mydomain.com/fullchain.pem; # 新增自定义域名证书时,在此追加映射条目 abc.com /etc/letsencrypt/live/custom/abc.com/fullchain.pem; } # 私钥路径映射 map $host $ssl_cert_key_file { default /etc/letsencrypt/live/mydomain.com/privkey.pem; # 新增自定义域名证书时,在此追加映射条目 abc.com /etc/letsencrypt/live/custom/abc.com/privkey.pem; }$ssl_cert_file和$ssl_cert_key_file即可。
注意事项
- 租户判断逻辑全部放在后端应用层实现,NGINX层不做租户映射规则匹配,避免租户量增长后配置维护成本爆炸
- 引导用户使用CNAME记录而非A记录指向服务器,后续服务器更换IP时无需通知所有用户调整解析
- 自定义域名接入时,通过certbot的
--webroot模式为用户域名申请单域名证书,申请完成后只需在map规则中追加对应条目,无需修改核心业务配置
内容的提问来源于stack exchange,提问作者TheBigK
相关产品推荐
相关产品推荐

