bg-tutorials

How to Generate a CSR in Node.js

This tutorial shows you how to generate a CSR for a Node.js application. Node.js has no built-in CSR generation tool, so you create the private key and the Certificate Signing Request with OpenSSL on the machine that will run Node, submit the CSR to your Certificate Authority, and then load the issued certificate into your app with fs.readFileSync() and https.createServer().

The steps below work on any operating system that ships OpenSSL, which covers every current Linux distribution, macOS, and Windows (via the official OpenSSL binaries or Git Bash). Modern OpenSSL signs requests with SHA-256 by default, so you do not need to add a digest flag.

Step 1: Make sure OpenSSL is installed

Check that OpenSSL is available on the machine that will run your Node.js app:

openssl version

You should see a line like OpenSSL 3.0.x or newer. If the command is not found, install it for your platform:

  • Debian, Ubuntu: sudo apt update && sudo apt install openssl
  • RHEL, AlmaLinux, Rocky Linux, Amazon Linux: sudo dnf install openssl (or sudo yum install openssl on older releases)
  • macOS: OpenSSL (LibreSSL on some versions, OpenSSL 3 if installed via Homebrew) is already in Terminal. To install the upstream build: brew install openssl@3.
  • Windows: install the official OpenSSL binaries, or use Git Bash, which ships with OpenSSL preinstalled.

Step 2: Generate the private key and CSR

Generate the key and CSR on the machine that will run Node.js. The private key is created next to the CSR and must stay on that machine. Running these commands somewhere else and then copying the key around defeats the point of having a private key in the first place.

Run the following command. It creates a 2048-bit RSA private key and a matching CSR in one step, with the subject and Subject Alternative Names (SANs) supplied inline so OpenSSL does not stop to ask questions:

openssl req -new -newkey rsa:2048 -nodes \
-keyout yourdomain.key \
-out yourdomain.csr \
-subj "/C=US/ST=YourState/L=YourCity/O=YourCompany/CN=yourdomain.com" \
-addext "subjectAltName=DNS:yourdomain.com,DNS:www.yourdomain.com"

What each part does:

  • -newkey rsa:2048 generates a new 2048-bit RSA key. 2048-bit is the current minimum public CAs accept; you can use rsa:4096 for a larger key, or switch to ECDSA (see below).
  • -nodes leaves the private key unencrypted so Node.js can read it at startup without prompting for a passphrase. Node’s https module does support a passphrase option for an encrypted key, but the passphrase still has to come from somewhere on the machine (a config file, an environment variable, or a secret manager).
  • -keyout and -out name the private key and the CSR files.
  • -subj supplies the certificate subject. Put your real company name, state, and city here, not the placeholders. CN (Common Name) is your primary domain.
  • -addext “subjectAltName=…” lists every hostname the certificate must cover. Public CAs validate against the SAN list, so include the Common Name here too. The -addext flag needs OpenSSL 1.1.1 or newer, which every current OS ships.

Replace yourdomain.com with your actual domain throughout. To cover extra hostnames, add them to the SAN list separated by commas, for example DNS:api.yourdomain.com. For a wildcard, include both the wildcard and the bare domain: DNS:*.yourdomain.com,DNS:yourdomain.com.

If you prefer an ECDSA key (smaller and faster, with P-256 widely supported), generate the key and CSR like this instead:

openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \
-keyout yourdomain.key \
-out yourdomain.csr \
-subj "/C=US/ST=YourState/L=YourCity/O=YourCompany/CN=yourdomain.com" \
-addext "subjectAltName=DNS:yourdomain.com,DNS:www.yourdomain.com"

Interactive mode (without -subj)

If you would rather have OpenSSL prompt you for each field, drop the -subj flag:

openssl req -new -newkey rsa:2048 -nodes \
-keyout yourdomain.key -out yourdomain.csr \
-addext "subjectAltName=DNS:yourdomain.com,DNS:www.yourdomain.com"

OpenSSL will ask for the following details:

  • Country Name (C): the two-letter ISO country code of your organization (for example, US).
  • State or Province Name (S): the full state or province where your company is registered (for example, California). Do not abbreviate.
  • Locality Name (L): the city where your business is registered (for example, San Jose).
  • Organization Name (O): the legal name of your company (for example, GPI Holding LLC). For a DV (Domain Validated) certificate, leave it blank and press Enter.
  • Organizational Unit Name (OU): deprecated since September 2022 and ignored by public CAs. Leave it blank.
  • Common Name (CN): the fully qualified domain name (FQDN) you are securing, for example yourdomain.com. For a wildcard, use *.yourdomain.com.
  • Email Address: optional. Leave it blank.
  • A challenge password: obsolete. Leave it blank.

Step 3: Locate and protect your files

List the current directory to confirm both files were created:

ls

You should see two new files:

  • yourdomain.key: your private key. Keep it on the server, back it up securely, and never send it to anyone, including the Certificate Authority. Whoever holds the key can impersonate your site.
  • yourdomain.csr: your Certificate Signing Request. This is the file you submit to the SSL provider.

On Linux or macOS, set strict permissions on the private key right away so only the user that runs Node.js can read it:

chmod 600 yourdomain.key

If Node.js runs under a dedicated service account (for example, node or www-data), also set the owner so the process can read the key:

sudo chown node:node yourdomain.key

Step 4: Verify the CSR (optional but recommended)

Before you submit it, check that the CSR contains the right subject and SANs and that its signature is valid. This decodes the request locally with OpenSSL:

openssl req -noout -text -verify -in yourdomain.csr

Confirm that the Subject line shows your details, that X509v3 Subject Alternative Name lists every hostname you expect, and that the signature check prints verify OK. The signature algorithm should read sha256WithRSAEncryption (or ecdsa-with-SHA256 for an ECDSA key). If you would rather not use the command line, paste the CSR into our online CSR decoder to read the same fields in a browser.

Step 5: Submit your CSR

To copy the CSR for your order, print its contents:

cat yourdomain.csr

You will see a block of text like this:

-----BEGIN CERTIFICATE REQUEST-----
MIIBozCB... (a long string of characters)
-----END CERTIFICATE REQUEST-----

Copy the entire block, including the —–BEGIN CERTIFICATE REQUEST—– and —–END CERTIFICATE REQUEST—– lines (each marker has five hyphens on either side). That whole block is your CSR. Paste it into the order form during your purchase, and keep the matching private key in place on the server.

If you would rather not use the command line, you can also build the request with our online CSR Generator. Note that it generates the private key in your browser, so save that key yourself and move it onto the Node.js server.

What happens after the CA issues the certificate

Once the CA validates the CSR and issues the certificate, you will typically receive your server certificate (a .crt file named after your domain) plus one or more intermediate certificates, sometimes bundled into a .ca-bundle file. Node.js loads these in JavaScript: concatenate the server certificate and the intermediates into a single fullchain.crt file, then read it with fs.readFileSync() and pass it to https.createServer():

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

const options = {
  key: fs.readFileSync('/path/to/yourdomain.key'),
  cert: fs.readFileSync('/path/to/fullchain.crt'),
  minVersion: 'TLSv1.2'
};

https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Welcome to a Node.js HTTPS server\n');
}).listen(443);

That fullchain pattern is what most production setups use. The full walkthrough (including an ES modules example, an alternative ca: array approach, and an Express example) is covered in our Node.js SSL installation tutorial.

A note on production deployments. In 2026 most Node.js apps that handle public traffic run behind a reverse proxy or cloud load balancer (NGINX, HAProxy, Caddy, AWS ALB, Cloudflare, Fastly) that terminates TLS on the edge and forwards plain HTTP or HTTP/2 to Node on a high local port. In that pattern, the certificate (and the CSR you generated above) lives on the proxy or the load balancer, not on the Node process itself. Letting Node.js terminate TLS directly is perfectly fine for development, internal services, and small deployments; for a public production app, terminating TLS at the edge is the more common shape.

Save 10% on SSL Certificates when ordering from SSL Dragon today!

Fast issuance, strong encryption, 99.99% browser trust, dedicated support, and 25-day money-back guarantee. Coupon code: SAVE10

A detailed image of a dragon in flight
Written by

I've been writing for SSL Dragon for over 10 years, focusing entirely on SSL certificates and digital security. My job is to take complex cybersecurity topics and strip away the jargon, making sure you get the clear, practical information you need to keep your website safe.