Obtain and configure ssl certificate on nginx with letsencrypt - Manual Configuration

These instructions walk through setting up a lets encrypt certificate on a server manually they have drawn heavily from digitaloceans tutorial

Note

FQDN is short for fully qualified domain name for it contains a host and a domain e.g. red.hatherleigh.info

Important

EFF have updated and renamed their certificate manager to certbot. They include scripts called both certbot-auto and letsencrypt-auto. For their latest installation instructions see letsencrypt installation instructions. It’s probably worth keeping an eye on that page as their instructions have changed several times.

Installation

Update and ensure that requirements are installed:

sudo apt update
sudo apt -y install git bc

Clone the letsencrypt repository:

sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Note

If you are getting a certificate for a site for the first time you’ll need to configure a port 80 server block (http rather than https)

Add the following to the nginx server block for the site:

location ~ /.well-known {
    allow all;
}

Ensure that root is at the top level in the server block not inside a location:

root <your web projects repository>/files/<server FQDN>

Check your nginx configurations with the command:

sudo nginx -t

Reload the nginx configuration with the command:

sudo service nginx reload

Obtain the certificate

Note

The letsencrypt command allows you add multiple site names to a single certificate by specifing -d multiple times e.g. -d hatherleigh.info -d red.hatherleigh.info -d www.hatherleigh.info

Hint

you need to create a DNS A record for each host you specify to prove that you own the domain

To obtain the certificate run the letsencrypt command (replace the sections in <> with the server names you are applying a certificate for):

cd /opt/letsencrypt
./letsencrypt-auto certonly -a webroot --webroot-path=<your web projects repository>/files/<server FQDN> -d <server FQDN> [-d <other server FQDN if required>]

If this is the first time you have run letsencrypt it will install itself and prompt for an email address and prompt to accept the terms and conditions

If successful you’ll receive the following message:

IMPORTANT NOTES:
- If you lose your account credentials, you can recover through
  e-mails sent to sammy@digitalocean.com
- Congratulations! Your certificate and chain have been saved at
  /etc/letsencrypt/live/<server FQDN>/fullchain.pem. Your
  cert will expire on <Expiry Date>. To obtain a new version of the
  certificate in the future, simply run Let's Encrypt again.
- Your account credentials have been saved in your Let's Encrypt
  configuration directory at /etc/letsencrypt. You should make a
  secure backup of this folder now. This configuration directory will
  also contain certificates and private keys obtained by Let's
  Encrypt so making regular backups of this folder is ideal.
- If like Let's Encrypt, please consider supporting our work by:

  Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
  Donating to EFF:                    https://eff.org/donate-le

Record the path and expiration date of your certificate for use later.

This will create the following files in /etc/letsencrypt/live/<server FQDN>

  • cert.pem: Your domain’s certificate
  • chain.pem: The Let’s Encrypt chain certificate
  • fullchain.pem: cert.pem and chain.pem combined
  • privkey.pem: Your certificate’s private key

Problems obtaining a certificate

If you have problems it’s usually a problem with access to the .well-known directory. To test this create a temporary file in the .well-known directory of the server root and ensure that you can see it from the web e.g. if you create the file:

<your web projects repository>/files/<server FQDN>/.well-known/tmp.html

You should be able to browse to that file using either:

https://<server FQDN>/.well-known/tmp.html
or
http://<server FQDN>/.well-known/tmp.html

Generate Strong Diffie-Hellman Parameters

Create a hardened dhparam certificate using this command:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Configure Nginx server block to use the certificate

edit the server include file:

vim /etc/nginx/include/<server FQDN>.conf

it should now look like this:

server {
  listen 80;
  server_name <Server FQDN> [<other server names if required>];
  return 301 https://$host$request_uri;
}

server {
  client_max_body_size 20m;
  listen 443 ssl;
  server_name <Server FQDN>;

  ssl_certificate /etc/letsencrypt/live/<Server FQDN>/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/<Server FQDN>/privkey.pem;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
  ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
  ssl_session_timeout 5m;
  ssl_session_cache shared:SSL:50m;
  ssl_stapling on;
  ssl_stapling_verify on;

  add_header Strict-Transport-Security max-age=15768000;

  root <your web projects repository>/files/<Server FQDN>;

  location ~ /.well-known {
      allow all;
  }

  location /media {
      alias <your web projects repository>/files/<Server FQDN>/public/;
  }

  location /private/ {
      internal;
  }

  location /robots.txt {
      alias <your web projects repository>/project/<Server FQDN>/live/web_static/robots.txt;
  }

  location ~ ^/favicon.(\w*)$ {
      alias <your web projects repository>/project/<Server FQDN>/live/web_static/ico/favicon.$1;
  }

  location /static {
      alias <your web projects repository>/project/<Server FQDN>/live/web_static/;
  }

  location / {
      include          uwsgi_params;
      uwsgi_param      UWSGI_SCHEME https;
      uwsgi_pass       127.0.0.1:3043;
  }
}

Ensure that your nginx configuration is correct:

sudo nginx -t

Reload the nginx configuration:

sudo service nginx reload

You can now test your configuration from a browser

You can also use the Qualys SSL Labs Report to see how your server configuration scores:

https://www.ssllabs.com/ssltest/analyze.html?d=<Server FQDN>

Configure Auto renewal

You can check and renew all the certificates managed by a letsencrypt installation using the command:

/opt/letsencrypt/letsencrypt-auto renew

then if certificates are renewed reload the nginx configuration

You can configure the system to do this automatically by adding this command the root crontab

sudo crontab -e

Add the following:

39 2,14 * * * /opt/letsencrypt/letsencrypt-auto renew --no-self-update >> /var/log/le-renew.log
44 2,14 * * * /etc/init.d/nginx reload

Note

Letsencrypt recommend that you do not self upgrade from cron. You should periodically check for updates see below

Check for updates to the letsencrypt certbot

The auto renewal process run from cron does not self update you should check your server regularly to ensure that the letsencrypt software stays up to date.

If you have installed from our salt configuration this check will be performed when a state.apply is requested. To check manually, log on to the server and execute the following commands:

cd /opt/letsencrypt
sudo git pull
sudo ./letsencrypt-auto renew

This will recreate the virtual environment install all the requirements for letsencrypt and then check for and renew any out of date certificates.

Stop renewing a certificate

The certbot does not have an option to stop renewing a certificate to do this manually perform the following procedure:

sudo rm -r /etc/letsencrypt/live/<primary domain name>
sudo rm -r /etc/letsencrypt/archive/<primary domain name>
sudo rm -r /etc/letsencrypt/renewal/<primary domain name>.conf

e.g. for the site www.hatherleigh.info:

sudo rm -r /etc/letsencrypt/live/www.hatherleigh.info
sudo rm -r /etc/letsencrypt/archive/www.hatherleigh.info
sudo rm /etc/letsencrypt/renewal/www.hatherleigh.info.conf