Https/SSL for free, step by step guide


#1

After reading that Roli is considering https for juce.com (http://www.juce.com/forum/topic/you-are-collecting-credit-card-numbers-non-secure-site) I decided to publish my to date private guide here. Bear in mind that I'm not an expert on this, I'm a sole audio software developer.

Two month ago I switched from a regular certificate to one from letsencrypt.org. Such a certificate is free and you can renew it AUTOMATICALLY. That's the awesome part! You don't have to spend hours each year to renew your certificate.

They have their own huge scripts for your sever, you need to give those quite some rights and they will modify your server. That's not cool at all. Luckily there are alternatives, small scripts you can easily verify yourself and that don't need any modifications of your server. In particular acme-tiny.

 


***********************************
How to set up the let's encrypt SSL
***********************************

 

Sources:
    https://www.metachris.com/2015/12/comparison-of-10-acme-lets-encrypt-clients/
    https://github.com/diafygi/acme-tiny


Background
==========

ACME
----

The Automated Certificate Management Environment (ACME) protocol defines a way of automatically obtaining trusted certificates without human intervention. First, the control of a domain has to be proven, then the agent can request, renew and revoke certificates.

Certificates issued by Let's Encrypt are valid for 90 days, and are expected to be renewed automatically. More background information can be found on https://letsencrypt.org/howitworks/technology/

At the time of writing, these rate limits has been in place:

- 10 Registrations per IP per 3 hours
- 5 Certificates per Domain per 7 days (incl. subdomains)

Once the agent has an authorized key pair, requesting, renewing, and revoking certificates is simple - just send certificate management messages and sign them with the authorized key pair.

SSL Certs & Signing
-------------------

Obtaining a valid SSL certificate generally includes the following steps:

1. You create a private and public key pair on the server.
2. You create a Certificate Signing Request (CSR) which includes the domain name, organization name, the public key, and other information. The CSR is signed with your private key.
3. You send the CSR to the certificate authority.
4. The certificate authority signs the request, thus producing a public certificate.
5. You use the public certificate in your webserver.

 


Step 0: Get ACME tiny
=====================

    mkdir ~/ssl_acme_tiny
    cd ~/ssl_acme_tiny
    git clone https://github.com/diafygi/acme-tiny.git .


Step 1: Create a private key
==================================================

    cd ~/ssl_acme_tiny
    openssl genrsa 4096 > acme-tiny/account.key
    chmod 660 acme-tiny/account.key


Step 2: Create a certificate signing request (CSR) for your domains
===================================================================

The ACME protocol (what Let's Encrypt uses) requires a CSR file to be submitted to it, even for renewals. You can use the same CSR for multiple renewals. NOTE: You can't use your account private key as your domain private key!

    #generate a domain private key
    openssl genrsa 4096 > domain.key
    chmod 660 domain.key

    #for multiple domains (use this one if you want both www.yoursite.com and yoursite.com)
    openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:<yourAwesomeCompany>.com,DNS:www.<yourAwesomeCompany>.com,DNS:mail.<yourAwesomeCompany>.com")) > acme-tiny/domain.csr


Step 3: Make your website host challenge files
==============================================

You must prove you own the domains you want a certificate for, so Let's Encrypt requires you to host some files for them. This script will generate and write those files in the folder you specify, so all you need to do is make sure that this folder is served under the ".well-known/acme-challenge/" url path.

   mkdir ~/ssl_acme_challenge

Example for nginx

    server {
        listen 80;
        server_name <yourAwesomeCompany>.com www.<yourAwesomeCompany>.com;
    
        location /.well-known/acme-challenge/ {
            alias /home/<yourUserName>/ssl_acme_challenge/;
            try_files $uri =404;
        }
    
        ...the rest of your config
    }


Step 4: Get a signed certificate
================================

    cd ~/ssl_acme_tiny/acme-tiny
    python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /home/<yourUserName>/ssl_acme_challenge/ > ./signed.crt    


Step 5: Install the certificate
===============================

For nginx, you need to append the Let's Encrypt intermediate cert to your cert

    wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
    cat signed.crt intermediate.pem > chained.pem


Step 6: Setup an auto-renew cronjob
===================================

Congrats! Your website is now using https! Unfortunately, Let's Encrypt
certificates only last for 90 days, so you need to renew them often. No
worries! It's automated! Just make a bash script called e.g. renew_cert.sh
and add it to your crontab. The content of that file:

    #!/bin/bash

    acmeTinyDirectory=/home/<yourUserName>/ssl_acme_tiny/acme-tiny/
    acmeChallengeDirectory=/home/<yourUserName>/ssl_acme_challenge/

    python $acmeTinyDirectory/acme_tiny.py --account-key $acmeTinyDirectory/account.key --csr $acmeTinyDirectory/domain.csr --acme-dir $acmeChallengeDirectory > $acmeTinyDirectory/signed.crt || exit
    wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > $acmeTinyDirectory/intermediate.pem
    cat $acmeTinyDirectory/signed.crt $acmeTinyDirectory/intermediate.pem > $acmeTinyDirectory/chained.pem
chmod 775 renew_cert.sh

Add it to the crontab of  <yourUserName>:

    # ------------------  SSL cert refresh -------------------------

    # runs at 4 o clock on the 5th of each month
    #min  hour  mday  month wday  command
    0     4     5    *     *     /home/<yourUserName>/ssl_acme_tiny/acme-tiny/renew_cert.sh 2>> /home/<yourUserName>/ssl_acme_tiny/acme-tiny/acme_tiny.log

 

Add to the crontab of root:

    # ------------------  SSL cert refresh -------------------------
    # runs at 4:05 on the 5th of each month
    #min  hour  mday  month wday  command
    5     4     5    *     *     service nginx reload > /dev/null

 

Cheers,

Samuel


Wrong site security certificate being used?
#2

Update:
Replace https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem with https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem

Otherwise you’ll now get a ‘This Connection is Untrusted’ in Firefox.


#3

Thanks, very useful info… I’ve often wondered when dealing with SSL certificates how much its worth paying for them.