nginx 使用不同的证书配置通配符域

nginx configure wildcard domains with different certificates

在我使用 nginx 的小虚拟主机配置中,我遇到了一个新问题。

我尝试使用 server_name 通配符

为我的每个虚拟主机设置一个“webmail”子域
server_name ~^(webmail\.)?(?<domain>.+)$;

因为我所有的域都有自己的 ssl 证书,所以我也想为 webmail 子域使用正确的证书。证书配置为通配符证书,如 *.domain1.com

所以 webmail.domain1.com 应该使用 *.domain1.com 的证书,而 webmail.domain2.net 应该使用 *.domain2.net 证书。

我最初猜测尝试了以下方法,但无法启动 nginx,因为它不接受路径中的变量:

ssl_certificate /etc/letsencrypt/live/$domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$domain/privkey.pem;

有没有一种方法可以使用覆盖所有 webmail.* 个子域的单个配置文件来实现此配置?

是的,但不是您希望的那样...

您遇到的问题是 nginx 需要先终止 SSL,然后才能读取流内容以让主机 header 设置 server_name 来决定需要哪个证书和密钥终止 SSL。这就是为什么变量和映射永远不会起作用的原因,因为在 nginx 需要读取证书的时候它们还不存在。

(我相信 OpenResty 中有 Lua 函数处理证书处理,但我认为这更多是关于证书 life-cycles 而不是为每个请求选择一个 on-the-fly你想要什么。)

实现此目的的方法是编写您的 conf 生成脚本,使用 perl、python、bash,无论您喜欢什么。描述一个只需要给定域名的通用 server 块模板,并为每个域生成一个副本。它们可以全部放在一个文件中,也可以 include 从不同的文件中提取,任何适合您的都行。

提示:如果你用点前缀命名一个conf文件,比如.server-tpl.conf,那么它会被通常的include conf.d/*.conf忽略。这样,您可以将此模板与其他 conf 文件放在一起,但只会加载已填充的副本。