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 "/CN=www.attosol.com" > 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

wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py

2.7 Execute the script

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

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

Parsing account key...
Parsing CSR...
Registering account...
Registered!
Verifying www.attosol.com...
www.attosol.com 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 - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > 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;
    server_name yoursite.com, www.yoursite.com;

    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_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
    ssl_session_cache shared:SSL:50m;
    ssl_prefer_server_ciphers on;

    ...the rest of your config
}

server {
    listen 80;
    server_name yoursite.com, www.yoursite.com;

    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 renew-certificates.sh in any location and type in the following commands:

cd /path/to/acme_tiny.py
sudo python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /usr/share/nginx/html/challenges/ > ./signed.crt
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > 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 renew-certificates.sh

Execute it by typing ./renew-certificates.sh 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/renew-certificates.sh 2>> /path/2/logs/acme_tiny.log

Conclusion

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.

What next?

Well, stay tuned for upcoming articles. You may contact us at contact@attosol.com for your software and consultancy requirements.

© 2023, Attosol Private Ltd. All Rights Reserved.