Skip to content

An Express HTTPS server with a self-signed certificate

How to create a self-signed HTTPS certificate for Node.js to test apps locally

To be able to serve a site on HTTPS from localhost you need to create a self-signed certificate.

A self-signed certificate is sufficent to establish a secure, HTTPS connection for development purposes. Although browsers will complain that the certificate is self-signed (and as such is not trusted).

To create the certificate you must have OpenSSL installed on your system.

You may have it installed already, just try typing openssl in your terminal.

If not, on a Mac you can install it using brew install openssl (if you use Homebrew). Otherwise, search on Google “how to install openssl on “.

Once OpenSSL is installed, run this command:

openssl req -nodes -new -x509 -keyout server.key -out server.cert

You will be prompted to answer a few questions. The first is the country name:

Generating a 1024 bit RSA private key
...........++++++
.........++++++
writing new private key to 'server.key'
-----
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:

Then your state or province:

State or Province Name (full name) [Some-State]:

Your city:

Locality Name (eg, city) []:

…and your organization name:

Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:

You can leave all of these empty.

Just remember to set this to localhost:

Common Name (e.g. server FQDN or YOUR name) []: localhost

…and to add your email address:

Email Address []:

That’s it! Now you have 2 files in the folder where you ran the original command:

Both files will be needed to establish the HTTPS connection, and depending on how you are going to setup your server, the process to use them will vary.

Those files need to be put in a place reachable by the application, and then you’ll need to configure the server to use them.

This is an example using the https core module and Express:

const https = require('https')
const app = express()

app.get('/', (req, res) => {
  res.send('Hello HTTPS!')
})

https.createServer({}, app).listen(3000, () => {
  console.log('Listening...')
})

Without adding the certificate, if I connect to https://localhost:3000 this is what the browser will show:

without-cert

With the certificate in place:

const fs = require('fs')

//...

https.createServer({
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.cert')
}, app).listen(3000, () => {
  console.log('Listening...')
})

Chrome will tell us that the certificate is invalid (since it’s self-signed), and will ask us to confirm before continuing (however, the HTTPS connection will still work):

with-cert


→ Here's my latest YouTube video

→ Get my Express.js Handbook

→ I wrote 17 books to help you become a better developer, download them all at $0 cost by joining my newsletter

JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025

Bootcamp 2025

Join the waiting list