Certificate Depot

Guides

Home › Guides › Node.js

Self-Signed SSL Certificate for Node.js HTTPS Server

Run a Node.js HTTPS server with a self-signed certificate — native, Express, and Fastify examples.

Node.js has built-in HTTPS support via the https module. You just need to load your certificate and key, and pass them as options to createServer.

Step 1: Generate the Certificate

Use cert-depot.com for a browser-friendly cert, or:

openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout key.pem -out cert.pem -days 365 \
  -subj "/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

Native https module

const https = require("node:https");
const fs = require("node:fs");

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

https.createServer(options, (req, res) => {
    res.writeHead(200, { "Content-Type": "text/plain" });
    res.end("Hello over TLS!\n");
}).listen(3443, () => {
    console.log("Listening on https://localhost:3443/");
});

Express

const express = require("express");
const https = require("node:https");
const fs = require("node:fs");

const app = express();
app.get("/", (req, res) => res.send("Hello over TLS!"));

https.createServer({
    key: fs.readFileSync("key.pem"),
    cert: fs.readFileSync("cert.pem"),
}, app).listen(3443, () => {
    console.log("Express listening on https://localhost:3443/");
});

Fastify

const fastify = require("fastify")({
    https: {
        key: require("node:fs").readFileSync("key.pem"),
        cert: require("node:fs").readFileSync("cert.pem"),
    },
});

fastify.get("/", async () => ({ hello: "world" }));
fastify.listen({ port: 3443 });

Making fetch / axios / node-fetch trust the certificate

By default, Node.js rejects self-signed certificates when acting as a client. For development only:

# Run with NODE_TLS_REJECT_UNAUTHORIZED=0 — insecure, dev only
NODE_TLS_REJECT_UNAUTHORIZED=0 node client.js

A better approach: point Node.js at the cert via NODE_EXTRA_CA_CERTS:

NODE_EXTRA_CA_CERTS=./cert.pem node client.js

Or pass it per-request with the ca option in https.Agent.

Never set NODE_TLS_REJECT_UNAUTHORIZED=0 in production. It disables all certificate validation, making every HTTPS call vulnerable to MitM attacks. Use NODE_EXTRA_CA_CERTS instead.

PFX / PKCS#12 alternative

Instead of separate key and cert, you can load a single PFX file:

https.createServer({
    pfx: fs.readFileSync("cert.pfx"),
    passphrase: "your-password",
}, app).listen(3443);

Our generator produces PFX files directly.

Need a self-signed certificate? Use our free generator — browser-compatible SANs, RSA or ECDSA, ZIP or PFX. No signup, no ads, keys never stored.

Further Reading