Implementing SSL - Free & Quick

What is SSL?

Secure Sockets Layer (SSL) is the standard security technology for establishing an encrypted link between a web server and a browser. This link ensures that all data passed between the web server and browsers remain private and integral.

The Importance of SSL

In 2014, Google announced that sites with HTTPS will get a minor ranking boost. This alone is a good enough reason to have SSL for your website (or blog). Still, 79 of the web's top 100 non-Google sites don't use SSL by default. The story about security for the other websites is much worse. The reasons are aplenty and is primarily attributed to concerns related to speed, investment, lack of knowledge, complexity & trouble involved.

We were guilty too of not having SSL, and the main reason was that, we... were... lazy! In this article, I will show you precisely how we did it, and exactly how much time and money it took.

Our Setup

Simply put, our site is hosted on Nginx web server using AWS. If you are using AWS or Azure, your steps might be very similar to ours. Essentially, you need to have a Shell access in order to make it simple. If you don't have Shell access, check this page for your options.

Step 1: Find a Certificate Authority

The first step is to get a certificate from a Certificate Authority (CA). There are quite a few well known providers where you can $buy$ it from. However, this article focuses on Let's Encrypt which is a CA that provides free certificates. It allows you to automate certificate issuance and installation with no downtime.

Step 2: Installation Steps

Let's Encrypt recommends that people with shell access use the Certbot ACME client. As of 25th Nov, 2016... the instructions didn't work on AWS Linux for Certbot. So, I decided to use one of the options as suggested here > acme-tiny. Read their documentation to learn more.

2.1 Create a private key

The first step is to create a private key using openssl like so:

openssl genrsa 4096 > account.key  

2.2 Certificate Signing Request (CSR)

Create a certificate signing request for your domains (Your account private key cannot and should not be used as a domain private key)

openssl genrsa 4096 > domain.key  
openssl req -new -sha256 -key domain.key -subj "/" > domain.csr  

2.3 Create a challenge folder

This folder plays an important role while making a request. The script requests a fixed URL /.well-known/acme-challenge/ and the URL is configured in the next step. For now, create a folder like so:

sudo mkdir -p /usr/share/nginx/html/challenges/  

2.4 Modify Nginx configuration

In your server block, add the following location:

location /.well-known/acme-challenge/ {  
  alias /usr/share/nginx/html/challenges/;
  try_files $uri =404;

2.5 Reload Nginx configuration

sudo nginx -s reload  

2.6 Get the script

Github Repository for acme-tiny


2.7 Execute the script

The downloaded script needs to be executed with appropriate parameters as follows:

sudo python --account-key ./account.key --csr ./domain.csr --acme-dir /usr/share/nginx/html/challenges/ > ./signed.crt

Parsing account key...  
Parsing CSR...  
Registering account...  
Verifying verified!  
Signing certificate...  
Certificate signed!  

2.8 Create the appended Certificate

For Nginx, you must append the Let's Encrypt intermediate certificate to your certificate.

wget -O - > intermediate.pem  
cat signed.crt intermediate.pem > chained.pem  

2.9 Copy Certificate

Copy the certificate where Nginx could read from.

sudo cp chained.pem /path/to/chained.pem  
sudo cp domain.key /path/to/domain.key  

2.10 Update Nginx Configuration

Update your configuration appropriately

server {  
    listen 443;

    ssl on;
    ssl_certificate /path/to/chained.pem;
    ssl_certificate_key /path/to/domain.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_session_cache shared:SSL:50m;
    ssl_prefer_server_ciphers on;

    ...the rest of your config

server {  
    listen 80;

    location /.well-known/acme-challenge/ {
        alias /usr/share/nginx/html/challenges/;
        try_files $uri =404;

    ...the rest of your config

2.11 Reload Configuration

If you have followed along well, your website should now be accessible using SSL. Congratulations!!!

Step 3: Set up a cron job

Let's Encrypt certificates expires every 90 days, so you need to renew them often. A regular certificate that you buy lasts a whole year by default and at the end of the year, you are supposed to pay again!

But with a free certificate that needs to be renewed every 3 months (and that too, automatically), it shouldn't be too much of a complain. Right? Well... almost! The only task remaining is to automate this process by writing a script.

3.1 Create a Bash script file

Create a file in any location and type in the following commands:

cd /path/to/  
sudo python --account-key ./account.key --csr ./domain.csr --acme-dir /usr/share/nginx/html/challenges/ > ./signed.crt  
wget -O - > intermediate.pem  
cat signed.crt intermediate.pem > chained.pem  
sudo cp chained.pem /path/to/chained.pem  
sudo cp domain.key /path/to/domain.key  
sudo nginx -s reload  

3.2 Set Permissions

sudo chmod 755  

Execute it by typing ./ and ensure that it works as expected.

NOTE: There is a rate limit of just 5 every 7 days (for every domain), and you should not renew certificates unnecessarily by executing this script.

3.3 Set up crontab

Type crontab -e and add a cron job like so:

#Executes on day 1 of every month.
0 0 1 * * /path/to/ 2>> /path/2/logs/acme_tiny.log  


SSL is not a panacea, but it is one step forward towards more secure infrastructure and every step counts. With free certificates at your disposal, there is no reason why your website shouldn't be on SSL. All of this put together helped us use an SSL certificate for free in less than an hour of work.

Rahul Soni

⌘⌘ Entrepreneur. Author. Geek. ⌘⌘

Kolkata, India

Subscribe to Attosol Technologies

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!