Installing an SSL Certificate on Node.js
Andrew JohnsonShare
Node.js takes a different approach to HTTPS than traditional web servers. There is no configuration file to edit and no service to bind. The SSL Certificate is loaded directly in application code through the built-in https module, which gives developers complete control and also complete responsibility for getting the chain right.
This guide covers the standard https server setup, correct Intermediate Certificate handling, and the reverse proxy question that every production Node.js deployment eventually faces.
Prerequisites and Required Files
You need your issued SSL Certificate file and the ca-bundle containing the Intermediate Certificates, both available in the tracking system after issuance. View Our Tracking & SSL Management 🔗
You also need the Private Key generated alongside your Certificate Signing Request (CSR). Trustico® does not retain Private Keys, so the copy on your server is the only one in existence. Learn About Generating a CSR 🔗
Place all three files in a directory outside the public and static folders of your application. Restrict the Private Key so only the application user can read it, for example with chmod 600 yourdomain.key.
Creating the HTTPS Server
The https module accepts the SSL Certificate, the Private Key, and the chain as options when the server is created. Reading the files synchronously at startup is the normal pattern, since the application cannot serve traffic without them anyway.
const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('/etc/ssl/private/yourdomain.key'), cert: fs.readFileSync('/etc/ssl/certs/yourdomain.crt'), ca: fs.readFileSync('/etc/ssl/certs/yourdomain.ca-bundle') }; https.createServer(options, (req, res) => { res.writeHead(200); res.end('HTTPS is working'); }).listen(443);
The ca option is the part most tutorials omit, and skipping it produces a server that works in desktop browsers while failing on mobile devices and in command line clients. Desktop browsers quietly repair incomplete chains from their cache, which hides the problem until a stricter client connects. Learn About Intermediate Certificates 🔗
An alternative pattern concatenates the SSL Certificate and ca-bundle into one file and passes the combined file through the cert option alone. Both approaches produce an identical chain on the wire, so choose whichever fits your deployment tooling.
Express, Fastify, and similar frameworks plug into the same mechanism. Pass the request handler of the framework to https.createServer in place of the inline function shown above.
Binding Port 443 Without Root Privileges
Ports below 1024 are privileged on Linux, and running a Node.js application as root to reach port 443 is poor practice. The cleaner options are granting the Node.js binary the bind capability, or listening on a high port behind a redirect.
sudo setcap 'cap_net_bind_service=+ep' $(which node)
Many production deployments avoid the question entirely by terminating Transport Layer Security (TLS) at a reverse proxy such as NGINX, with Node.js listening on a local port behind it. The SSL Certificate then installs on the proxy rather than in the application. Learn About SSL Offloading 🔗
Verifying the Installation
Restart the application and load the site over HTTPS. Then run an external scan, which checks the chain exactly as a fresh client receives it and catches the missing ca option mistake immediately. Trustico® provides free checking tools for this purpose. Explore Our Trustico® SSL Tools 🔗
Troubleshooting Common Installation Problems
An error reading key values mismatch or a TLS handshake failure at startup means the Private Key does not pair with the SSL Certificate being loaded. This usually traces to a CSR that was regenerated after submission. A reissue against the current CSR resolves it cleanly. Learn About Reissuing Your SSL Certificate 🔗
An EACCES error on listen means the process lacks permission for the privileged port. Apply the capability grant shown above, or move the application behind a proxy.
Tip : Node.js reads the SSL Certificate files once at startup, so a reissued SSL Certificate does not take effect until the application restarts. Build the restart into your replacement procedure to avoid serving an expired SSL Certificate from memory.
Chain errors reported only by mobile devices or tools such as curl mean the ca option is missing or points at the wrong file. Add the ca-bundle and restart.
Professional Installation Assistance
Application-level HTTPS is quick to set up, but production environments mixing proxies, containers, and multiple services can complicate where the SSL Certificate belongs.
Trustico® offers a Premium Installation service where our technicians complete the installation on your behalf. Discover Our Premium Installation Service 🔗