V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
fourstring
V2EX  ›  NGINX

请问为何配置文件中用 set 指令设置的变量不能被解析?

  •  
  •   fourstring · 2018-06-11 22:21:49 +08:00 · 2864 次点击
    这是一个创建于 2375 天前的主题,其中的信息可能已经有所发展或是发生改变。
    server {
    ...
    set $ssl_root /etc/letsencrypt;
    set $domain a.com;
    ssl_certificate      $ssl_root/$domain.rsa.pem;
    ssl_certificate_key  $ssl_root/$domain.rsa.key;
    ...
    }
    

    有关配置如上,我想达到的效果就是调用/etc/letsencrypt/下的有关证书文件a.com.rsa.pem以及a.com.rsa.key。但是运行 nginx 后报错信息如下:

    nginx: [emerg] BIO_new_file("/usr/local/nginx/conf/$ssl_root/$domain.rsa.pem") failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/usr/local/nginx/conf/$ssl_root/$domain.rsa.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)
    

    从报错信息中来看,nginx 并没有解析配置文件中设置好的变量,而是将它们作为纯字符串。我并没有在编译时加上--without-http_rewrite_module参数,但 set 指令似乎没有正常工作,请问可能有哪些问题?多谢各位大佬

    编译参数如下:

    ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-http_v2_module --with-openssl=../openssl-${OPENSSL_VER} --with-openssl-opt='enable-tls1_3' --add-module=../nginx-ct 
    

    PS:有关文件的确存在

    6 条回复    2018-06-12 15:54:12 +08:00
    ryd994
        1
    ryd994  
       2018-06-12 01:14:53 +08:00 via Android   ❤️ 1
    因为 SSL 证书是在读取配置时解析
    而 set 是在处理请求时才执行
    也就是说,等你 set,SSL 连接都已经建立了
    ssl_certificate 指令会不会展开变量都是个问题

    不如说说你到底什么目的,说不定有更直接的办法。
    caola
        2
    caola  
       2018-06-12 01:25:51 +08:00   ❤️ 1
    都这么写了,直接写正确的路径就可以了,还要 set 来做什么?
    dndx
        3
    dndx  
       2018-06-12 02:49:56 +08:00   ❤️ 2
    ssl_certificate 不支持变量解析,因为是在 config 阶段就读取了证书文件,没有运行时的动态行为。

    据我所知,目前开源的项目里能达到你要的效果的只有 OpenResty 的 [ssl_certificate_by_lua_block]( https://github.com/openresty/lua-nginx-module#ssl_certificate_by_lua_block),可以做到同一个 server 根据 SNI server_name 使用不同的证书。
    fourstring
        4
    fourstring  
    OP
       2018-06-12 06:56:09 +08:00 via Android
    @ryd994 谢谢大佬解答 我试图用变量解决问题就是因为用了双证书,证书存放路径要重复好多遍
    ryd994
        5
    ryd994  
       2018-06-12 13:49:16 +08:00 via Android   ❤️ 1
    写个小脚本,生成单独的配置文件,一堆 ssl_certificate,然后 include 进去。
    比如 find /etc/letsencrypt -name *.pem -print0 | xargs -0 -i echo "ssl_certificate {};"
    caola
        6
    caola  
       2018-06-12 15:54:12 +08:00
    @fourstring 原来是想要根据域名调用对应的 SSL 证书,这个使用 OpenResty 来搞就很简单啊。
    我的 https://goto.world/ ( AD 一下),就是使用 OpenResty + Redis 实现的,
    把证书的文本直接放在 Redis 里,再根据 SNI 的 server_name 来读取并使用对应的证书,
    我现在为了 QUIC 逐步的从 OpenResty 迁移到 Golang 来实现这一功能了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4779 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 09:26 · PVG 17:26 · LAX 01:26 · JFK 04:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.