hazardous

thoughts, things, etc. from andrew snow

nginx odds and ends: TLS

nginx! a cruel mistress.

through the years i have deployed nginx as a wonderful solution for alot of projects. however, i never really perfected a good 'one size fits all' nginx config - no single set of files that would require only a small amount of tweaking to fit a wide variety of use cases.

this will be my attempt to come to understand nginx, from the ground up.

one server, two server

this is my starting setup that i use to run two websites, hazardous and because the internet, from a single nginx installation.

becausethe.net.conf

server {
       listen 80;
       listen [::]:80;
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

       server_name becausethe.net;

       root /path/to/becausethe.net/public_html;
       index index.php index.html;

       location / {
               try_files $uri $uri/ =404;
       }

       location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    ssl_certificate /path/to/live/becausethe.net/chain.key; 
    ssl_certificate_key /path/to/becausethe.net/priv.key; 

zardo.us.conf

server {
        listen 80;
        listen [::]:80;
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name www.zardo.us zardo.us;
            return 301 https://ha.zardo.us$request_uri;
}

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

       server_name ha.zardo.us;

       root /path/to/zardo.us/public_html;
       index index.php index.html;

#        location / { try_files $uri $uri/ =404;}

        location / { try_files $uri $uri/ @rewrite; }

        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php-fpm.sock;
    }

                location @rewrite {
                        rewrite ^/(.*)$ /index.php?_=$1 last;
                }

    ssl_certificate /path/to/live/becausethe.net/chain.key;
    ssl_certificate_key /path/to/live/becausethe.net/priv.key;

}

playing nice with https

you might notice something: both files use the exact same keys for SSL, located at path/to/live/becausethe.net/*.key.

why? it's because of a quirk that results from the way SSL and, in particular, http/2 operate: the server opens a single, secure connection with the server. however, it can only ask for one certificate... which becomes a problem when you have individual certificates for multiple websites on a single server.

to solve this, i generated a single set of keys for all my domains: certbot certonly --nginx -d becausethe.net -d www.becausethe.net -d zardo.us -d ha.zardo.us -d www.zardo.us -d sub1.zardo.us

cleaning up redundancy

since i'm using one set of keys, defining the ssl_certificate parameter twice in two separate files becomes overkill.

thankfully, nginx is designed to be very modular and extensible. in this case, i might create a file called ssl.conf in my nginx/conf.d/ directory:

ssl.conf

    ssl_certificate /path/to/live/becausethe.net/chain.key;
    ssl_certificate_key /path/to/live/becausethe.net/priv.key;

nginx can be directed to use the above parameters by making sure it knows where to look, as defined in /path/to/nginx/nginx.conf:

[...]
        include /etc/nginx/conf.d/*.conf;
[...]