What's inside
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](http://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.
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!