Serve local HTTPS
Run a Node.js HTTPS server
Load the lab certificate and key into a minimal local HTTPS server bound to loopback.
Time to put the lab certificate to work. An HTTPS server is an application listener plus a certificate and its matching private key. Node.js ships all of it in the standard library, so we need zero dependencies.
Create server.mjs in the folder that holds app.key and app.crt:
import https from 'node:https'
import fs from 'node:fs'
https.createServer({
key: fs.readFileSync('app.key'),
cert: fs.readFileSync('app.crt'),
}, (request, response) => {
response.end('secure lab\n')
}).listen(8443, '127.0.0.1')
The options object is where TLS happens. key is the server’s private key. cert is the certificate we issued. The second argument to listen binds the server to 127.0.0.1 only. Keep the first lab on loopback: nothing outside your machine can reach it, which is what you want while practicing.
Run it:
node server.mjs
No output means it started. Let’s confirm port 8443 is bound to loopback only:
lsof -nP -iTCP:8443 -sTCP:LISTEN
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# node 70632 flavio 14u IPv4 0x9687... 0t0 TCP 127.0.0.1:8443 (LISTEN)
127.0.0.1:8443 in the NAME column confirms the loopback bind. If you saw *:8443 instead, the server would be listening on every interface. The -nP flags keep addresses and ports numeric. Without -P, lsof prints the port as pcsync-https, which is the service name registered for 8443 and not what you want to read.
Now probe it from a second terminal:
curl https://127.0.0.1:8443/
# curl: (60) SSL certificate problem: unable to get local issuer certificate
That error is correct behavior. curl doesn’t trust your lab CA, so verification fails. The next lessons fix this the right way, by giving curl the hostname and the root. Not by turning verification off.
One failure worth knowing. If key and cert don’t belong together, Node refuses to start:
Error: error:05800074:x509 certificate routines::key values mismatch
Node won’t serve a broken identity. When you see this, you loaded a key from one generation and a certificate from another. Re-check which files you copied. There’s a lesson later on how to prove which key matches which certificate without exposing either.
Before moving on, run chmod 600 app.key if you haven’t, and keep the practice server on your own computer. It’s a lab, not a deployment.
Lesson completed