'NGINX access-rights using string-interpolated file location

I found something curious about the nginx configuration. Whenever I put a string-literal as certificate/key-file location everything works fine. But since I need a bit more dynamic logic I tried maps. But apparently when you include a variable into the file-string, nginx doesn't use its root privileges meaning it cannot open the certificate?

example (this works perfectly):

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    server_name _;
    
    ssl_certificate           /etc/letsencrypt/live/mydomain.com/cert.pem;
    ssl_certificate_key       /etc/letsencrypt/live/mydomain.com/privkey.pem;
    
    # rest of the configuration stuff
}

example (this doesn't somehow):

map $host $cert_name {
    mydomain.com        mydomain.com;
    www.mydomain.com    mydomain.com;
    default             mydomain.com;
}


server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    server_name _;
    
    ssl_certificate           /etc/letsencrypt/live/$cert_name/cert.pem;
    ssl_certificate_key       /etc/letsencrypt/live/$cert_name/privkey.pem;
    
    # rest of the configuration stuff
}

This wil yield in the following error message:

cannot load certificate "/etc/letsencrypt/live/mydomain.com/cert.pem": BIO_new_file() failed (SSL: error:0200100D:system library:fopen:Permission denied:fopen('/etc/letsencrypt/live/mydomain.com/cert.pem','r') error:2006D002:BIO routines:BIO_new_file:system lib) while SSL handshaking, client: #client-ip#, server: 0.0.0.0:443

additional info:

OS: Ubuntu 20.04
nginx: nginx/1.18.0 (Ubuntu)  built with OpenSSL 1.1.1f  31 Mar 2020  TLS SNI support enabled
nginx started as root user?: yes
letsencrypt folder permissions: default

Would this be a security feature? or a bug?

In any case, is there a work around for this?



Solution 1:[1]

For if anyone stumbles on this problem. I found the answer in the letsencrypt documentation.

Basically the /etc/letsencrypt/live and /etc/letsencrypt/archive directories are created with permission 0700 for legacy reasons. When using the latest version of cerbot it is safe to set the permissions to 0755. The command they provided is:

chmod 0755 /etc/letsencrypt/{live,archive}

This allows non-root users to access all public certificates, while the private-keys are still only accessible by the root user/super-users. As it turns out, this is exactually what nginx does which means everything should work after changing the permissions.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 n247s