Using SSL with NodeJS and OpenShift

While building my latest project website I decided it would be nice to finally use custom SSL. Yes, I know, I should do it by default on all of my sites. It's good practise....but it can be hard (especially if you are doing it for free).

I already use LetsEncrypt for my OpenVPN home connection, so that was my first port-of-call for an SSL certificate. The main problem is generating the certificates, specifically proving that you own the domain you need the certificate for. LetsEncrypt provide a number of mechanisms to do this:
  • Using their 'certbot' tool on the server you need the certificate for
  • Adding a TXT record to DNS
  • Providing a 'known' response on the domain being requested
I decided on the latter of these options as I had successfully used it on my OpenVPN installation (unlike the DNS option which I couldn't get running). I am also running on OpenShift so using 'Certbot' is a problem.

How I did it..

setup

I use NodeJS for most of my 'hobby sites' these days, so I decided to add the '/.well-known/acme-challenge/XXXXXXXX' route to my node application and configure it with environment variables.

    // Lets encrypt response
    var letsEncryptUrl = process.env.LETS_ENCRYPT;
    var letsEncryptResponse = process.env.LETS_ENCRYPT_RESPONSE;

    if( letsEncryptResponse != undefined && letsEncryptResponse != undefined) {
      self.app.get('/.well-known/acme-challenge/' + 
           letsEncryptUrl, function (req, res) {
        res.send(letsEncryptResponse);
        res.end();
      });
    }

GitHub GIST

It can be seen fully implemented in my latest INSPIRE Viewer (Source code)

It uses 'dotenv' to load two environment variables:

  • LETS_ENCRYPT - The token needed at the end of the URL
  • LETS_ENCRYPT_RESPONSE - The response expected
So now we can set the environment variables, restart the app and it will respond to the LetsEncrypt challenge correctly :)

Getting the certificates

Now we need to ask LetsEncrypt for a certificate. To do this, clone the repo : 

git clone https://github.com/letsencrypt/letsencrypt

and run the following command...

./letsencrypt-auto certonly -a manual -d {domain}

This will now output the two parameters you need for the environment variables.  I use the following commands to setup on OpenShift:

rhc set-env LETS_ENCRYPT=XXXXXXX --app=app_name
rhc set-env LETS_ENCRYPT_RESPONSE=XXXXXXX --app=app_name

Now restart the OpenShift application and press 'continue' on LetsEncrypt.  

That's it, the certificates are now generated and stored locally.  They can then be uploaded by either the command line, rhc application, or through the web interface.

Certificate Renewal

LetsEncrypt certificates need to be renewed every 3 months....but it's baked into your application so renewal is now easy:
  1. Start renewal of certificates using LetsEncrypt script
  2. Update the two environment variables
  3. Restart the application
  4. Upload certificates
Done :)

If I get any time I might write a script to completely automate the process.  Have a look at https://inspire.digidad.space for a working example :)

Comments

Popular Posts