How to Install & Automate SSL Certificates on Node.js
PrintSSL/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