Not having SSL these days just won’t do.

After deploying my personal website, I couldn’t help but notice that Chrome and Safari were showing ’not secure’ in the address bar.

Setting up SSL is quite easy on cPanels and many hosting providers provide free SSL options. It’s really just a couple of clicks and some wait time before you are ready to go.

But, since we are working with Node and Express, things will be done differently.

Following guide has been tried and tested successfully on Ubuntu 18.04 x64 & Ubuntu 19.04 x64

Getting Started

Things you need,

  • The server is attached to the domain name.
  • Express app (without https).
  • Certbot.

Step 1: Install Cerbot

SSH into your Linux server if you haven’t already. Using the following commands will get you through.

    sudo add-apt-repository ppa:certbot/certbot
    sudo apt-get update
    sudo apt-get install certbot

Step 2: Generating the SSL Certificate

Now that you’ve successfully installed certbot, let’s use it to generate the certification.

Type this,

    certbot certonly --manual

Provide your email for renewing notices and allow it to log your IP address.

Now certbot will ask you to enter your domain names, comma, or space-separated.

For example, you can enter example.com and also www.example.com, if you want www.

May 2020 Update: If you don’t use ‘–manual’, it will ask you for the webroot path of your application. In most cases, this will be public directory of the express app, but you have put the full path. This is the recommended method, as it will automatically create files. This also makes it super easy to renew the certificate.

You will be asked to create a file at example.com/.well-known/acme-challenge/RandomFileName with some random string as it’s content. You will have to create the .well-known and acme-challenge directories. You might have to open another ssh session to create this file.

In express, you can put these directories and the file in the public directory. See serving static files in Express to setup public folder for serving static resources.

Make sure to start your server, just so the file is accessible to certbot when it checks.

If all is done well, press Enter. Congratulations, you’ve generated the privkey.pemcert.pem, and chain.pem.

Step 3: Editing your Express app for HTTPS

Open your main app file and make such changes,

const express = require("express");
const https = require("https");
const http = require("http");
const fs = require("fs");
const app = express();

// your other code

// https server
https
  .createServer(
    {
      key: fs.readFileSync(
        "/etc/letsencrypt/live/example.com/privkey.pem",
        "utf8"
      ),
      cert: fs.readFileSync(
        "/etc/letsencrypt/live/example.com/cert.pem",
        "utf8"
      ),
      ca: fs.readFileSync(
        "/etc/letsencrypt/live/example.com/chain.pem",
        "utf8"
      ),
    },
    app
  )
  .listen(443, () => console.log("HTTPS Server Started"));
// http server
http.createServer(app).listen(80, () => console.log("HTTP Server Started"));

That’s it!

Start your app and you’re done. Test your application at https://example.com.

What else can be done?

You should redirect your HTTP requests to https. How? Here’s a way, add this middleware to your app.

app.use((req, res, next) => {
  if (!req.secure) {
    return res.redirect("https://" + req.headers.host + req.url);
  }
  next();
});