Nginx/Laravel多租户场景下用户自定义域名SSL配置方案咨询
整体实现方案(已在生产环境落地验证)
1. 域名解析校验逻辑(Laravel侧实现)
- 用户提交自定义域名后,先做基础校验:排除非法字符、泛域名(若不支持)、顶级域名合法性校验,避免无效请求
- 调用PHP原生
dns_get_record()函数做解析校验:- 校验A记录是否指向你方服务器公网IP
- 校验CNAME是否指向你方分配给租户的统一解析域名(例如
*.tenant.yourdomain.com) - 首次校验不通过的域名推入延迟重试队列,每10分钟校验一次,最多重试24小时,解析生效后自动进入下一流程
- 校验通过的域名标记为「待签发证书」状态,推入证书处理队列
2. 证书自动签发逻辑
- 服务器优先安装
acme.sh作为证书签发工具,比certbot更轻量,适合批量自动化场景,无需交互操作 - 统一使用HTTP-01挑战模式,无需对接用户域名解析商,只要域名解析到你方服务器即可完成校验:
- 提前在Nginx全局配置中新增挑战路径的统一规则,一次配置永久生效,无需后续每次新增域名修改:
# 放在Nginx http块中,作为80端口默认服务 server { listen 80 default_server; server_name _; location /.well-known/acme-challenge/ { root /var/www/acme-challenge; allow all; } # 其他未匹配到的80请求可跳转到你方主站 location / { return 301 https://yourmaindomain.com$request_uri; } } - Laravel侧通过
symfony/process组件调用acme.sh命令,避免命令注入风险,参考命令:acme.sh --issue -d 用户自定义域名 -w /var/www/acme-challenge - 读取命令返回状态码,状态码为0则代表签发成功,将证书公钥、私钥存储路径写入对应域名的数据库记录,标记为「待更新Nginx配置」
- 签发失败的域名推入重试队列,每30分钟重试一次,最多重试3次,失败后触发通知提醒用户检查域名配置
- 提前在Nginx全局配置中新增挑战路径的统一规则,一次配置永久生效,无需后续每次新增域名修改:
3. Nginx配置自动更新逻辑
- 单独创建租户域名配置目录,例如
/etc/nginx/conf.d/tenant/,每个自定义域名对应单独的conf文件,命名规则可将域名的点替换为下划线(例如custom_example_com.conf),避免文件名冲突,主Nginx配置中引入该目录下所有conf文件即可 - 提前准备Nginx配置模板,替换对应变量即可生成配置文件,参考模板:
server { listen 80; server_name {{CUSTOM_DOMAIN}}; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name {{CUSTOM_DOMAIN}}; root /var/www/laravel/public; index index.php index.html; ssl_certificate {{SSL_CERT_PATH}}; ssl_certificate_key {{SSL_KEY_PATH}}; # 统一引用全局SSL参数配置,无需每个文件重复编写 include /etc/nginx/snippets/ssl-params.conf; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; # 替换为你方实际PHP版本对应的fpm地址 } } - 配置文件生成完成后,先执行
nginx -t校验配置合法性,校验通过才执行systemctl reload nginx重载配置,若校验失败直接删除无效配置文件,记录错误日志通知管理员排查,避免全局Nginx服务异常
4. 证书自动续期逻辑
- acme.sh默认自带定时续期任务,仅需额外配置续期成功后的钩子,自动触发Nginx重载即可,无需额外开发
- 可新增每日定时任务,扫描所有已签发的证书,距离到期不足30天的提前触发续期,避免默认任务异常导致证书过期
落地注意事项
- 所有服务器命令执行操作不要用root权限跑Laravel队列,单独创建权限受限的系统用户,仅给该用户分配acme.sh执行、租户Nginx配置目录写入、Nginx重载的sudo权限,避免安全风险
- 对单个租户可绑定的自定义域名数量做上限限制,避免恶意刷证书触发Letsencrypt的签发频率限制
- 所有流程全部走异步队列处理,不要在用户提交域名时同步执行,避免请求超时
内容的提问来源于stack exchange,提问作者JKA
相关产品推荐
相关产品推荐

