Good Nginx HTTPS Configuration

When configuring a web server for HTTPS, it is important to ensure your web server's configuration doesn't undermine the use of an encrypted session by using poor ciphers or not negotiating keys properly. Here are some Nginx options for a solid HTTPS/SSL configuration.

I'm not going to cover obtaining SSL certificates and will just assume you have some. If not, head over to Let's Encrypt and obtain one for free.

Once you've got your certificates figured out, within the Nginx configuration, find the appropriate server block and add the following:

server {
    listen      80;
    listen      443 ssl;

    root        /var/www/site;

    ssl_certificate             /path/to/cert/chain.pem;
    ssl_certificate_key         /path/to/cert/privkey.pem;
    ssl_protocols               TLSv1.2;
    ssl_prefer_server_ciphers   on;
    ssl_ciphers                 ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA;
    ssl_session_timeout         10m;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on; 
    ...
}

The first portion of the configuration tells the server on which ports to listen, the web root directory, and the paths to your SSL certificates. I'll briefly describe the other lines.

ssl_protocols

Here we list the protocols the server is allowed to negotiate. In this case, we are only negotiating TLSv1.2 or above.

ssl_prefer_server_ciphers

This specifies that server ciphers should be preferred over client ciphers, which helps prevent a malicious client (typically via a man-in-the-middle attack) from downgrading to a less secure cipher than you'd prefer. Enabling this forces the client to accept only from among the server's offered ciphers.

ssl_ciphers

The list of ciphers that will be supported for the HTTPS session. We only want strong ciphers here so keep this up-to-date as cryptography marches on.

ssl_session_timeout

This specifies the time during which a client may reuse the session parameters. Don't set this for too long.

ssl_session_cache

Specifies the types and sizes of caches that can be used to store session parameters. Here we are using a cache shared among all worker processes on the server and limiting the cache to 10 megabytes in size.

ssl_session_tickets

Specifies whether session resumption through the use of tickets is enabled or disabled. If enabled, according to the RFC, the "TLS server encapsulates the session state into a ticket and forwards it to the client. The client can subsequently resume a session using the obtained ticket." The configuration I have specified disables this functionality.

ssl_stapling

We are enabling the stapling of OCSP responses, which allows the server to send the certificate of the server's certificate issuer, saving client from having to make more roundtrips, which can be detrimental on a bandwidth constrained client.

ssl_stapling_verify

Enables the verification of OCSP responses by the server.

The other thing you'll want to do is to redirect all HTTP requests to HTTPS sites. This can easily be done with redirects in Nginx, even if you need to redirect multiple domains (e.g., you own the .com, .net, and .org TLDs for a domain and want them all to go to one TLD).

server {
    listen      80;
    listen      443 ssl;

    ...

    server_name  example.com www.example.com example.org www.example.org example.net www.example.net;

    if ($host = 'www.example.com') {
        rewrite ^/(.*)$ https://example.com/$1 permanent;
    }
    if ($host = 'http://example.com') {
        rewrite ^/(.*)$ https://example.com/$1 permanent;
    }
    if ($host = 'example.org') {
        rewrite ^/(.*)$ https://example.com/$1 permanent;
    }
    if ($host = 'www.example.org') {
        rewrite ^/(.*)$ https://example.com/$1 permanent;
    }
    if ($host = 'example.net') {
        rewrite ^/(.*)$ https://example.com/$1 permanent;
    }
    if ($host = 'www.example.net') {
        rewrite ^/(.*)$ https://example.com/$1 permanent;
    }

    ...

}

After all this is done, head over to the SSL Server Test run by Qualys SSL Labs. Enter your site and see what grade you receive.