Nginx: Redirect non-www and/or HTTP traffic to HTTPS and www domain

As you may have seen, I have now forced the use of HTTPS on my website. The certificate is signed by Let’s Encrypt and should therefore be recognized by all major browsers. I used the letsencrypt-nosudo tool made by Daniel Roesler to manually generate my certificates because I didn’t want the letsencrypt client to mess with my Nginx config files (I will probably try when I’m sure it is stable enough and working well on my server OS).

I wanted to redirect all traffic coming from the non-www domain to the www domain, and all HTTP traffic to HTTPS.

Basically, like this:

From To
http://brunoparmentier.be
http://www.brunoparmentier.be https://www.brunoparmentier.be
https://brunoparmentier.be

Here is the configuration I use on my server:

# Redirect all non-www traffic to www
server {
    server_name     brunoparmentier.be;
    listen          80;
    listen          443 ssl spdy;
    listen          [::]:80;
    listen          [::]:443 ssl spdy;

    ssl_certificate /path/to/certs/chained.pem;
    ssl_certificate_key /path/to/certs/domain.key;

    return          301 https://www.brunoparmentier.be$request_uri;
}

# Redirect all non-encrypted traffic to encrypted
server {
    server_name     www.brunoparmentier.be;
    listen          80;
    listen          [::]:80;

    return          301 https://www.brunoparmentier.be$request_uri;
}

# Main server block
server {
    server_name     www.brunoparmentier.be;
    listen          443 ssl spdy;
    listen          [::]:443 ssl spdy;

    ssl_certificate /path/to/certs/chained.pem;
    ssl_certificate_key /path/to/certs/domain.key;

    root            /usr/share/nginx/html/www;

    # ...
}

Note that I’m using a SAN (Subject Alternative Name) certificate which is valid for both brunoparmentier.be and www.brunoparmentier.be.

chained.pem contains this certificate, along with the “Let’s Encrypt Intermediate X1” certificate.

domain.key contains the certificate private key.