Obtain and configure ssl certificate on nginx with letsencrypt

The recommended method of using letsencrypt certificates with nginx is to obtain the certificate using the ‘certificate only’ method, authenticating via webroot. The webroot authentication uses a directory on the server that letsencrypt can view momentarily and issue the certificate.

This document contains instructions to do this using saltstack automation. If you want to setup the server manually, then follow these instructions, Obtain and configure ssl certificate on nginx with letsencrypt - Manual Configuration.

Configure using Salt

The salt configuration installs letsencrypt and configures each site to use the certificates supplied if both ssl and letsencrypt are configured in the site’s pillar. A cron task is created per server to renew all certificates periodically, this task logs output to /var/log/letsencrypt-renew.log. The server is also protected using a hardened Diffie Hellman dhparam certificate.

If you don’t have an existing certificate for your site, you need to configure it to use the http protocol to validate to letsencrypt that you are authorised to use the domain and then alter the configuration later to enable ssl and use the new certificate to sign the https protocol connections to your site. Follow the instructions in the section called Configuration without an ssl certificate then skip to Obtain the letsencrypt certificate

If you already have a existing valid ssl certificate configured on your site, you can use it to create an https connections to validate to letsencrypt that you are authorised to use the domain and then alter the configuration later to use the new certificate to sign the https protocol connections to your site. This is useful if you have an existing https site you wish to convert to using letsencrypt. Follow the instructions in the section called Configuration with an existing certificate then continue to Obtain the letsencrypt certificate

Configuration without an ssl certificate

On the master server, configure the pillar for your site use standard http as follows:

<domain>:
  package: <package>
  profile: django
  redirect: <redirect domain>
  celery: False
  db_pass: <password>
  db_type: <database type e.g. psql or mysql>
  opbeat: <opbeat id>
  secret_key: <django secret key>
  ssl: False
  # letsencrypt: True
  uwsgi_port: <uwsgi port>
  mail:
    mandrill_api_key: <mandrill key>
    mandrill_user_name: <mandril user name>
  recaptcha:
    norecaptcha_site_key: <norecaptcha site key>
    norecaptcha_secret_key: <norecaptcha secret key>

For a devpi server, edit the service.yb.devpi.sls file setting ssl to False and commenting out letsencrypt e.g:

devpi:
  domain: devpi.yourbiz.co.uk
  port: 4040
  ssl: False
  # letsencrypt: True

Note

The flag ssl is set to False (it must be present) and letsencrypt is commented out (disabled)

Having accepted your minion (if necessary), create or update your site using:

salt <minion name> state.highstate

Check the output to ensure that the site has been created

Configuration with an existing certificate

On the master server, configure the pillar for your site to use https as follows:

<domain>:
  package: <package>
  profile: django
  redirect: <redirect domain>
  celery: False
  db_pass: <password>
  db_type: <database type e.g. psql or mysql>
  opbeat: <opbeat id>
  secret_key: <django secret key>
  ssl: True
  # letsencrypt: True
  uwsgi_port: <uwsgi port>
  mail:
    mandrill_api_key: <mandrill key>
    mandrill_user_name: <mandril user name>
  recaptcha:
    norecaptcha_site_key: <norecaptcha site key>
    norecaptcha_secret_key: <norecaptcha secret key>

Note

The flag ssl is set to True (enabled) but letsencrypt is commented out (disabled). This will use ssl certificates obtained manually

Having accepted your minion (if necessary), create or update your site using:

salt <minion name> state.highstate

Check the output to ensure that the site has been created

Obtain the letsencrypt certificate

Warning

Run the following command as a user that can sudo (not the web user).

Log on to the minion and check and reload the nginx configuration:

sudo nginx -t
sudo service nginx reload

For a standard web site, run the command:

./bin/init-letsencrypt <server FQDN> [<redirect domain>]

For a devpi server, see the instructions above, run:

./bin/init-letsencrypt devpi.yourbiz.co.uk - /usr/share/nginx/html

Note

/usr/share/nginx/html is the root defined in /etc/nginx/include/devpi.conf.

init-letsencrypt is a script installed by our salt configuration:

It calls letsencrypt-auto with the certonly and webroot options and sets the webroot path and specifies the domain and optionally a redirect domain.

The init-letsencrypt script is installed into the bin folder of all users other than web. The web user has an opt directory - but the usual convention for a user directory that contains executable files is ~/bin. In order that there is only one copy of the script on the system, we installed the script into the /home/web/opt directory. The script requires sudo privilege (which web does not have), so we created a bin directory for each user and linked to the /home/web/opt/ copy of the script.

If this is the first time you have run letsencrypt on this server it will install a virtual environment and all the dependencies and then 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 so you can check at a later date.

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

Enable the letsencrypt certificate on your server

Having obtained the certificate using one of the methods above, log on to the master server and alter the pillar entry for the site to enable the flags for both ssl and letsencrypt - as shown in the following snippet (see above for the full pillar configuration):

secret_key: <django secret key>
ssl: True
letsencrypt: True
uwsgi_port: <uwsgi port>

For a devpi server, edit the service.yb.devpi.sls file setting ssl and letsencrypt to True e.g:

ssl: True
# letsencrypt: True

Now run:

salt <minion name> state.highstate

Then log on to the minion and type:

sudo service nginx reload

The system will now use the new letsencrypt certificate to provide https protocol connections.

Test

You can test your site using:

https://www.ssllabs.com/ssltest/analyze.html?d=<domain name>