Setting up HTTPS on Nginx with Certbot and Letsencrypt

Security of our applications is nearly as important as the business logic. As software developers we are completely aware of it. That’s why we follow all the good practices and avoid anti-patterns that may put our apps to danger. We update the libraries we use whenever a security patch is released. We look out for new vulnerabilities. Making our software as secure as possible and keeping it that way has become our point of honor. Nevertheless SSL and HTTPS tend to be overlooked by some of us. Maybe because it was a pain to obtain and set up the certificate? Maybe it was expensive? If those were your excuses not to secure your site with HTTPS, then you’re out of luck, because they’re no longer valid! Let’s Encrypt (https://letsencrypt.org/) is a Certificate Authority (CA) offering free certificates and a tool that makes it easy to obtain and renew them. In this post, we’ll explore how to use this tool (it’s called Certbot, by the way) and how to set up our Nginx server properly to use the certificate and provide secure connection.

We’re assuming we have a server with Ubuntu 16.04 and a user with `sudo` privileges. Let’s get into it.

Installing Certbot

First we need to install „ppa:certbot/certbot” repository:

sudo add-apt-repository ppa:certbot/certbot

 

Then update the apt package info and install Certbot:

sudo apt-get update

sudo apt-get install certbot

 

For setup instructions on other operating systems, visit https://certbot.eff.org/

Obtaining the certificate

In order to get the certificate, Let’s encrypt has to confirm that the domain we’re getting the certificate for belongs to us. To do that, Certbot creates a special filewe need to make available via our server. Then Let’s Encrypt validation server will make a request to reach the file. If it succeeds, validation is complete.

There are several Certbot plugins that automate the process. We’re going to use `Webroot`. (There’s also nginx plugin, but it alters the server configuration, and we don’t want that. That’s why we’re using Webroot instead).

When we request the certificate, Certbot will create the validation file in hidden `.well-known` directory. We have to serve files from that directory. To do so, edit your nginx configuration file and add new location block inside server section for your application:

location /.well-known {

    root /var/www/html/;

}

 

Now run syntax check and restart your nginx server:

sudo nginx -t

sudo systemctl restart nginx

 

After that, we can run certbot:

sudo certbot certonly -—webroot —-webroot-path=/var/www/html -d my-domain.com -d www.my-domain.com

 

Here we’re assuming that `/var/www/html` is the root directory of our server. It should exist if you’re using Nginx. If it’s not there -create it. You will have to enter your email address and accept the terms of service if Certbot wasn’t run on your machine before. After the operation is finished, you should see a block of text starting with `IMPORTANT NOTES:`. There you will have paths where your certificates has been saved. It’s best to copy this information and save it somewhere safe.

The certificate files should be created in `etc/letsencrypt/archive`. Certbot will also create symbolic links to them in `/etc/letsencrypt/live/<your-domain.com>/` along with a README file containing short explanation what generated files are for.

There should be four files:

  • cert.pem
  • fullchain.pem
  • privkey.pem
  • chain.pem

It’s a good idea to create a secure backup of those files.

Generating Diffie-Hellman group

This step is recommended to increase security. Use `openssl` to create a `dhparam.pem` file:

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

 

The `dhparam.pem` file will be created in `/etc/ssl/certs/dhparam.pem`. We will use it in `ssl_dhparam` setting in nginx configuration in the next step.

Configuring Nginx

In this step we will create a new server block for our application with https and modify the one we had so far for http. The file you’ll want to open usually lives in `/etc/nginx/sites-available/`. Let’s take a look at the settings we’ll place there.

 

First of all, enable ssl and use our certificate:

listen 443 ssl http2;

ssl_certificate /etc/letsencrypt/live/<your-domain.com>/fullchain.pem;

ssl_certificate_key /etc/letsencrypt/live/<your-domain.com>/privkey.pem;

 

Add `dhparam` pointing to the Diffie-Hellman group we created earlier:

ssl_dhparam /etc/ssl/certs/dhparam.pem;

 

Some other recommended settings:

ssl_prefer_server_ciphers: on;

ssl_ciphers: "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH”;

 

There are other nginx settings you can play with, explained in nginx documentation (http://nginx.org/en/docs/http/ngx_http_ssl_module.html).

 

We’ll add a command that will make Nginx redirect users from http to secure https connection, in the server block we had before (the one used with http):

return 301 https://$server_name$request_uri;

 

Your server configuration should look somewhat like this:

server {

    return 301 https://$server_name$server_uri;

    server_name example.com;

    listen 80;

}

 

server {

    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

    ssl_prefer_server_ciphers on;

    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    listen 443 ssl http2;

 

    location /.welll-known/ {

        root /var/www/html/;

    }

 

    … other settings … 

}

 

Now check your configuration for errors:

sudo nginx -t

 

… and restart the server:

sudo systemctl restart nginx

 

Now you should be able to access your site both with http and https!

 

Krzysztof Skarupa Krzysztof Skarupa

TAGS:

You may also like