Introduction

Secure Socket Layer or SSL is a super simple way to implement transport level security on your website. After google search engine started considering SSL as a key SEO parameter having SSL certificate for your website is a important aspect. In this blog post we will see how quickly we can generate a free SSL certificate using letsencrypt and start using it in node.js application.

Key Assumptions

You have basic understanding of Node.js application & you have already installed docker in your local dev environment and read my earlier post here, in which we have created sample node.js application. In this post we will make few changes to sample application to support HTTPS protocol. Also this post assumes you have a registered domain name and you have access and are authorized to make changes DNS records.

Setup Letsencrypt  environment (Non docker)

In case you do not want to use docker for generating SSL certificate, you can use certbot documentation here to setup environment ready for generating SSL generation using Letsencrypt.  

Setup Letsencrypt environment (Docker)

Once you verify your docker installation, Please execute following command.

 docker run --entrypoint="/bin/sh" -it --name certbot certbot/certbot:latest
Download cerbot image and run docker process

Above command would download latest image from docker hub, spin a process using same image and attach your process with interactive mode.

Generating SSL certificate

Letsencrypt provides you with multiple options to generate SSL certificate which is valid for duration of 90 days. After 90 days you can rerun same process or run renew process. In this post I will be covering DNS txt / DNS-01 challenge and HTTP-01 challenge.

  • DNS-01 Challenge: For DNS txt verification you will need access to your Domain configuration which would be provided by your domain name provider. For getting SSL certificate you will have to add entries to DNS records. Lets get started. Assuming you already have access to certbot environment via docker / linux, execute following command. Please note I will be creating certificate for www.shettyashwin.com, please replace this with your domain name.    
certbot certonly --manual -d *.shettyashwin.com
DNS TXT verification wildcard command

On enter, above command will prompt you information like. Please make sure you replace *.shettyashwin.com with your domain name.

  • Email ID: Which will be used for registration and sending alerts fews days before certificate expiry
  • Terms & Condition
  • Email Registration for Electronic Frontier Foundation: Based your choice you can opt in or ignore it
  • Register Server IP : Enter Yes

Here is screenshot with my inputs

DNS-01 Challenge wizard

Last line in above screenshot will provide you encrypted text which you will have to copy and add in your DNS records which will be verified by letsencrypt server.

Now open DNS records in your control panel provided by domain provider and add following detail

  • Type: TXT
  • Name: _acme-challenge
  • Value: [encrypted text generated in above wizard (check screenshot)]
  • TTL: 1/2 hour

Once this is  done wait for few minus just to make sure your DNS entry are refreshed by your domain provider. Now come back to certbot command prompt and press enter. This will verify and generate your SSL  certificate at /etc/letsencrypt/live/[your-domain-name]/. If you are using docker, you can use CP command to copy your  certificate locally.

  • HTTP-01 challenge: HTTP challenge will need some route to be setup in case if you are using node.js. Here is my node.js code which I have to used to setup this route.
var router = express.Router();
var sslKey = "";

router.get('/.well-known/acme-challenge/:key', (req, res, next) => {
    res.send(sslKey);
});

router.get('/.well-known/acme-challenge/:key/edit/:value', (req, res, next) => {
    sslKey = req.params.value;
    res.send(req.params.value);
});

module.exports = router;

Above code should allow you to set encrypted key via URL.  Make sure this route is mapped to root, which means it should be accessible via domain something like http://[your-domain-name]/.well-known  You will have to deploy this on server for which you are planing to get SSL certificate. For security reason please make sure you hide or remove this route once you are done with your SSL generation.

Once you deploy node.js code, get back to certbot environment and execute following command.

certbot certonly --manual -d www.shettyashwin.com
HTTP verification

This will prompt you to enter following parameter,

  • Email ID: Which will be used for registration and sending alerts fews days before certificate expiry
  • Terms & Condition
  • Email Registration for Electronic Frontier Foundation: Based your choice you can opt in or ignore it
  • Register Server IP : Enter Yes

Once you enter above values, you should see encrypted text. Screenshot for reference

HTTP-01 challenge wizard

To update value in the node.js route logic, open a browser and hit URL with this parameter. http://[your-domain-name]/.well-known/acme-challenge/[any-value]/edit/[file-text]

  • [any-value] : any text, value here does not matter while we are setting text for ssl verification
  • [file-text]: Text available below "Create a file containing just this data"

Once you hit the URL you should see value which you enter for [file-text]. After you verify this text press enter in certbot command prompt. Wizard will than verify value and generate certificate for your domain. Certificate will available at /etc/letsencrypt/live/[your-domain-name]/.

Here is the node.js code for creating HTTPS server.

const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem')
};

https.createServer(options, function (req, res) {
  res.end("hello world");
}).listen(8080);

Before running above code, please make sure you have copied your SSL certificate in node.js app.

Reference