How to Install & Automate SSL Certificates on Node.js

Print
  • 0

SSL/TLS automation for Node.js applications using ACME certificates ensures secure communication without manual renewal operations.

This guide uses the acme.sh client with External Account Binding (EAB) and covers installation, certificate issuance, PM2 integration, HTTPS configuration, and auto-renewal verification.

Node.js Server

Prerequisites:

  • ACME SSL subscription with EAB (EAB_KID and EAB_HMAC_KEY)
  • Node.js and npm installed (node -v, npm -v)
  • Domain pointing to server
  • Working Node.js application (port 80)
  • PM2 installed
  • Root/sudo access
  • Outbound access to ACME server (e.g. https://acme.sectigo.com/v2/DV)

1. Install acme.sh

Install ACME client:

curl https://get.acme.sh | sh

Load environment and verify:

source ~/.bashrc
acme.sh --version

Tip: ensure curl and git are installed.

2. ACME Account Registration (EAB)

acme.sh --register-account \
--server https://acme.sectigo.com/v2/DV \
--eab-kid EAB_KID \
--eab-hmac-key EAB_HMAC_KEY \
--accountemail you@example.com

Parameters:

  • SERVER – ACME CA URL
  • EAB_KID – account identifier
  • EAB_HMAC_KEY – authentication key
  • accountemail – notification email

3. Run Node.js with PM2

3.1 Install PM2

sudo npm install -g pm2
pm2 --version

3.2 Start application

pm2 start server.js --name yourapp-site

3.3 Auto-start on reboot

pm2 startup systemd
pm2 save
pm2 status

4. Issue SSL Certificate (Webroot)

acme.sh --issue \
-d yourdomain.com \
-d www.yourdomain.com \
-w /path/to/project/public \
--server https://acme.sectigo.com/v2/DV

Important: webroot must match Express static directory.

5. Install Certificate in Node.js

5.1 Create SSL directory

mkdir -p ~/yourapp-site/cert

5.2 Install certificate

acme.sh --install-cert -d yourdomain.com \
--key-file /path/to/ssl/yourdomain.key \
--fullchain-file /path/to/ssl/yourdomain.crt \
--reloadcmd "pm2 restart yourapp-site"

Note: app will restart automatically after renewal.

5.3 File permissions

sudo chown root:root /path/to/ssl/*
sudo chmod 600 /path/to/ssl/yourdomain.key
sudo chmod 644 /path/to/ssl/yourdomain.crt

For non-root users:

sudo chown <user>:<group> /path/to/ssl/yourdomain.key
sudo chmod 600 /path/to/ssl/yourdomain.key

6. Enable HTTPS in Node.js

6.1 Import modules

const express = require('express');
const fs = require('fs');
const https = require('https');
const http = require('http');
const path = require('path');

6.2 Express setup

const app = express();

app.use(express.static(path.join(__dirname, 'public')));

app.use(
'/.well-known/acme-challenge',
express.static(path.join(__dirname, 'public', '.well-known', 'acme-challenge'), { dotfiles: 'allow' })
);

6.3 Main route

app.get('/', (req, res) => {
res.send('Hello from yourdomain.com (HTTPS enabled)');
});

6.4 HTTP → HTTPS redirect

http.createServer((req, res) => {
res.writeHead(301, { Location: 'https://' + req.headers.host + req.url });
res.end();
}).listen(80);

6.5 HTTPS server

https.createServer({
key: fs.readFileSync('/path/to/ssl/yourdomain.key'),
cert: fs.readFileSync('/path/to/ssl/yourdomain.crt')
}, app).listen(443);
pm2 restart yourapp-site

7. Verification & Auto-Renew

  • Open https://yourdomain.com
  • Check SSL validity
crontab -l
acme.sh --renew -d yourdomain.com --force

Troubleshooting

  • Port 80 blocked – check firewall / lsof -i:80
  • Unauthorized – verify EAB and ACME server
  • Standalone conflict – use webroot mode only

Was this answer helpful?