This content originally appeared on DEV Community and was authored by SK
Backend engineering is one thing: getting two or more nodes to talk over the internet.
That’s your job. Everything you do, databases, APIs, protocols; boils down to this: can one machine send a packet to another, and can the other reply? That’s it.
Once that packet leaves your machine, whether from the client:
curl https://domain:443/
Or the server:
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from HTTPS server!\n');
You’ve lost control. That packet is now at the mercy of ISPs, data centers, and the network until it reaches the other side. A lot can go wrong in that space between.
TLS exists to make sure none of that “wrong” compromises your data.
It encrypts the packet in a way only the sender and receiver can understand. Even if someone intercepts it, they can’t read it. If your packet is raw text, that’s a grenade. TLS turns it into alien gibberish for anyone else.
Custom TLS is the backbone of internal systems(distributed systems), pipelines, IoT and tools in backend(e.g mTLS).
In this guide, we’ll build a simple HTTPS (TLS-enabled) server using Node.js. The concept, though, is universal.
TLS: Secret Language Between Machines
TLS lets two machines on the internet create a private language; one only they can understand.
You’ve probably seen that little “handshake” message in your browser when visiting a secure site. That’s not metaphor; it’s real. The client and server are negotiating a shared language, like:
You (Client) Server
----------- -------
"Hi! I speak English, Spanish,
and Klingon." ——→ "Cool, I’m Acme Corp. Here’s my passport
(a certificate from a trusted authority).
Let’s talk in Klingon (TLS 1.3)."
"Alright, passport checks out.
Let’s pick a secret code
and chat securely." ←—— "Agreed. Cipher locked in."
From now on, every message is encrypted.
Now; where do you get these certificates?
Usually, when you buy a domain, your registrar resells a certificate. But for local testing or internal services, we can generate our own using things like OpenSSL.
Step 1: Self-Signed Certs with OpenSSL
Let’s roll our own TLS certificates.
Create a working folder:
mkdir certs && touch server.js
Inside certs, we’ll generate both a Certification Authority (CA) and a server certificate signed by it.
Create a Certification Authority (CA)
openssl genrsa -out ca-key.pem 4096
openssl req -x509 -new -nodes -key ca-key.pem -days 3650 -out ca-cert.pem \
-subj "/C=US/ST=Test/L=Test/O=Test CA/OU=Dev/CN=MyTestCA"
This makes a pseudo-government; our own trusted root called MyTestCA.
Create the Server Certificate
# 1. Generate private key
openssl genrsa -out server-key.pem 4096
# 2. Create a signing request
openssl req -new -key server-key.pem -out server.csr \
-subj "/C=US/ST=Test/L=Test/O=MyApp/OU=Servers/CN=bunny.local"
# 3. Self-sign with your own CA
openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -days 365
bunny.localis our mock domain name.
Step 2: Spin Up an HTTPS Server
Now for the fun part serving over TLS.
server.js
import https from "node:https"
import path from "node:path"
import fs from "node:fs"
const PORT = 443
const CERT_DIR = path.resolve(process.cwd(), 'certs')
const tlscert = {
key: fs.readFileSync(path.join(CERT_DIR, 'server-key.pem')),
cert: fs.readFileSync(path.join(CERT_DIR, 'server-cert.pem')),
}
const server = https.createServer(tlscert, (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello from HTTPS server!\n')
})
server.listen(PORT, () => console.log(`Listening on port ${PORT}`))
Key point: you're using Node’s built-in https module instead of http. Pass in the TLS certs on creation.
Step 3: Test It
Run your server:
node server.js
Then hit it:
curl https://localhost:443/
You’ll get this error:
curl: (60) schannel: SEC_E_UNTRUSTED_ROOT - The certificate chain was issued by an authority that is not trusted.
Which makes sense; your OS doesn’t know who MyTestCA is.
Skip verification with:
curl -k https://localhost:443/
-ktells curl to accept self-signed certs.
Now you’ve got a fully functioning HTTPS server; with a language only you and your clients can speak.
Secure, private, tight.
Welcome to the encrypted internet.
Ever wondered what it really takes to build low-level Node.js tooling or distributed systems from scratch(which this post in an excerpt from)?
- Learn raw TCP
- Go over a message broker in pure JavaScript
- Go from "can code" to "can engineer"
Check out: How to Go from a 6.5 to an 8.5 Developer
—
Or maybe you're ready to master the dark art of authentication?
- From salting and peppering to mock auth libraries
- Understand tokens, sessions, and identity probes
- Confidently use (or ditch) auth-as-a-service or roll out your own?
Grab: The Authentication Handbook: With Node.js Examples
thanks for reading. 🙏
This content originally appeared on DEV Community and was authored by SK
SK | Sciencx (2025-07-22T11:16:33+00:00) How To Setup A Node HTTPS/TLS server: Internal systems.. Retrieved from https://www.scien.cx/2025/07/22/how-to-setup-a-node-https-tls-server-internal-systems/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.