letsencrypt

Lets Encrypt with an nginx reverse proxy

Here are instructions for obtaining a Let’s Encrypt certificate using the same webserver you are using as a proxy.

Requesting your initial certificate from Let’s Encrypt

Modify your server clause to allow the subdirectory .well-known to be served from a local directory, eg:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    […]
    location /.well-known {
            alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}

http://sub.domain.com/.well-known is where the Let’s Encrypt servers will look for the answers to the challenges it issues.

You can then use the certbot client to request a certificate from Let’s Encrypt using the webrootplugin (as root):

certbot certonly --webroot -w /var/www/sub.domain.com/ -d sub.domain.com -d www.sub.domain.com

Your key, certificate, and certificate chain will now be installed in /etc/letsencrypt/live/sub.domain.com/

Configuring nginx to use your certificate

First create a new server clause like this:

server {
    listen 443 ssl;

    # if you wish, you can use the below line for listen instead
    # which enables HTTP/2
    # requires nginx version >= 1.9.5
    # listen 443 ssl http2;

    server_name sub.domain.com www.sub.domain.com;

    ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem;

    # Turn on OCSP stapling as recommended at 
    # https://community.letsencrypt.org/t/integration-guide/13123 
    # requires nginx version >= 1.3.7
    ssl_stapling on;
    ssl_stapling_verify on;

    # Uncomment this line only after testing in browsers,
    # as it commits you to continuing to serve your site over HTTPS
    # in future
    # add_header Strict-Transport-Security "max-age=31536000";

    access_log /var/log/nginx/sub.log combined;

    # maintain the .well-known directory alias for renewals
    location /.well-known {
        alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here as in your port 80 configuration
        […]
    }
}

Reload nginx:

service nginx reload

Verify that HTTPS now works by visiting https://sub.domain.com and https://www.sub.domain.com in your browser (and any other browsers you specifically wish to support) and checking that they don’t report certificate errors.

Recommended: also review raymii.org: Strong SSL Security on nginx and test your configuration at SSL Labs.

(Recommended) Redirect HTTP requests to HTTPS

Once you have confirmed that your site works with the https:// version of the URL, rather than have some users served insecure content because they went to http://sub.domain.com, redirect them to the HTTPS version of the site.

Replace your entire port 80 server clause with:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    rewrite     ^   https://$host$request_uri? permanent;
}

You should also now uncomment this line in the port 443 configuration, so that browsers remember to not even try the HTTP version of the site:

add_header Strict-Transport-Security "max-age=31536000";

Automatically renew your certificate

You can use this command (as root) to renew all certificates known to certbot and reload nginx using the new certificate (which will have the same path as your existing certificate):

certbot renew --renew-hook "service nginx reload"

certbot will only attempt to renew certificates that are more than 60 days old, so it is safe (and recommended!) to run this command very regularly, and automatically if at all possible. Eg, you could put the following command in /etc/crontab:

# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16   * * *   root   certbot renew --quiet --renew-hook "service nginx reload"

You can test renewals with either a dry-run, which will contact Let’s Encrypt staging servers to do a real test of contacting your domain, but won’t store the resulting certificates:

certbot --dry-run renew

Or you can force an early renewal with:

certbot renew --force-renew --renew-hook "service nginx reload"

Source: https://serverfault.com/questions/768509/lets-encrypt-with-an-nginx-reverse-proxy/784940#784940