Version Overview

Node.js 12.x
Deprecated
Node.js 12 is an older LTS version that supports basic HTTPS functionality but lacks some modern TLS features. Maintenance stopped in 2022.
⚠️ 注意: Node.js 12 has stopped maintenance and has security risks. It is strongly recommended to upgrade to Node.js 18 or 20.
Node.js 14.x
Stable Version
Node.js 14 is a stable LTS version that supports TLS 1.3 and provides better SSL/TLS support. Configuration method is similar to Node.js 12.
Node.js 16.x
Stable Version
Node.js 16 is a stable LTS version that enables TLS 1.3 by default, providing better performance and security.
Node.js 18.x
Recommended Version
Node.js 18 is the currently recommended LTS version that supports all modern SSL/TLS features, including full TLS 1.3 support.
✅ 推荐: Node.js 18 is the most stable and recommended version currently, supporting all modern SSL/TLS features.
Node.js 20.x
Current Version
Node.js 20 is the current LTS version that provides the latest security features and performance optimizations, fully supports TLS 1.3.
Node.js Version Status TLS 1.2 TLS 1.3 OpenSSL Version Recommended Use
Node.js 12.x Deprecated ⚠️ Needs Configuration 1.1.1
Node.js 14.x Stable 1.1.1
Node.js 16.x Stable 1.1.1
Node.js 18.x LTS 3.0.x ✅ Recommended
Node.js 20.x LTS 3.0.x

Certificate Format Handling

Node.js can directly use .crt and .key files, or use merged certificate chain files.

Certificate File Preparation

Step 1: Merge Certificate Chain (if needed)

# # Merge main certificate and intermediate certificatecat your_domain.crt intermediate_ca.crt > fullchain.crt # # Ensure private key file exists# your_domain.key

File Permission Settings

# # Set private key file permissions (owner read-only)chmod 600 your_domain.key # # Set certificate file permissionschmod 644 fullchain.crt
💡 提示: Node.js supports PEM format certificate and private key files, which is the most common format. If your certificate is in another format, you need to convert it first.

HTTPS Server Configuration

Basic HTTPS Server (Native Node.js)

const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt') }; const server = https.createServer(options, (req, res) => { res.writeHead(200); res.end('Hello HTTPS!'); }); server.listen(443, () => { console.log('HTTPS server running on port 443'); });

Configuration with Intermediate Certificate

const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/your_domain.crt'), ca: [ fs.readFileSync('/path/to/intermediate_ca.crt'), fs.readFileSync('/path/to/root_ca.crt') ] }; const server = https.createServer(options, (req, res) => { res.writeHead(200); res.end('Hello HTTPS!'); }); server.listen(443);
📝 Configuration Notes:
  • key:key: Private key file path
  • cert:cert: Certificate file path (can be merged fullchain.crt)
  • ca:ca: Intermediate certificate array (optional, not needed if cert already contains full chain)

Express.js SSL Configuration

Express.js Basic Configuration

const express = require('express'); const https = require('https'); const fs = require('fs'); const app = express(); app.get('/', (req, res) => { res.send('Hello HTTPS!'); }); const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt') }; https.createServer(options, app).listen(443, () => { console.log('Express HTTPS server running on port 443'); });

Express.js Advanced Configuration

const express = require('express'); const http = require('http'); const https = require('https'); const fs = require('fs'); const app = express(); app.get('/', (req, res) => { res.send('Hello!'); }); // HTTP 服务器(重定向到 HTTPS) http.createServer((req, res) => { res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url }); res.end(); }).listen(80); // HTTPS 服务器 const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt') }; https.createServer(options, app).listen(443, () => { console.log('HTTPS server running on port 443'); });

Version Configuration Differences

Node.js 12.x Configuration

const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt'), secureProtocol: 'TLSv1_2_method', // 或 TLSv1_3_method ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384' }; const server = https.createServer(options, (req, res) => { res.writeHead(200); res.end('Hello HTTPS!'); }); server.listen(443);

Node.js 14.x / 16.x Configuration

const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt'), minVersion: 'TLSv1.2', maxVersion: 'TLSv1.3', ciphers: 'TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384' }; const server = https.createServer(options, (req, res) => { res.writeHead(200); res.end('Hello HTTPS!'); }); server.listen(443);

Node.js 18.x / 20.x Configuration (Recommended)

const https = require('https'); const fs = require('fs'); const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt'), minVersion: 'TLSv1.2', maxVersion: 'TLSv1.3', ciphers: [ 'TLS_AES_256_GCM_SHA384', 'TLS_AES_128_GCM_SHA256', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-RSA-CHACHA20-POLY1305' ].join(':'), honorCipherOrder: true }; const server = https.createServer(options, (req, res) => { res.writeHead(200); res.end('Hello HTTPS!'); }); server.listen(443);
⚠️ Important Differences:
  • Node.js 12 needs to explicitly specify TLS protocol version
  • Node.js 14+ supports TLS 1.3 by default, but explicit configuration is recommended
  • Node.js 18+ uses OpenSSL 3.0, cipher suite names may differ
  • New versions recommend using minVersion and maxVersion instead of secureProtocol

TLS Protocol Configuration

Enable TLS 1.2 and TLS 1.3

const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt'), minVersion: 'TLSv1.2', maxVersion: 'TLSv1.3' };

Disable Insecure Protocols

const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt'), minVersion: 'TLSv1.2', // // Disable TLS 1.0 and 1.1 rejectUnauthorized: true // // Reject invalid certificates};

Configure Cipher Suites (Node.js 18+)

const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt'), minVersion: 'TLSv1.2', maxVersion: 'TLSv1.3', ciphers: [ 'TLS_AES_256_GCM_SHA384', // // TLS 1.3 'TLS_AES_128_GCM_SHA256', // // TLS 1.3 'ECDHE-RSA-AES128-GCM-SHA256', // // TLS 1.2 'ECDHE-RSA-AES256-GCM-SHA384', // // TLS 1.2 'ECDHE-RSA-CHACHA20-POLY1305' // // TLS 1.2 ].join(':'), honorCipherOrder: true };
⚠️ Security Recommendations:
  • Disable SSLv2, SSLv3, TLSv1.0, TLSv1.1
  • Only enable TLS 1.2 and TLS 1.3
  • Use strong cipher suites
  • Regularly update Node.js version

HTTP to HTTPS Redirect

Use Middleware Redirect (Express)

const express = require('express'); const app = express(); // // Force HTTPS middlewareapp.use((req, res, next) => { if (req.header('x-forwarded-proto') !== 'https') { res.redirect(`https://${req.header('host')}${req.url}`); } else { next(); } }); app.get('/', (req, res) => { res.send('Hello HTTPS!'); }); // // Check protocol (for reverse proxy)app.listen(3000);

Method 2: Use Nginx Reverse Proxy

const express = require('express'); const enforce = require('express-enforces-ssl'); const app = express(); // 强制 HTTPS app.use(enforce()); app.get('/', (req, res) => { res.send('Hello HTTPS!'); }); app.listen(3000);

原生 Node.js 重定向

const http = require('http'); const https = require('https'); const fs = require('fs'); // HTTP 服务器(重定向) http.createServer((req, res) => { res.writeHead(301, { 'Location': 'https://' + req.headers['host'] + req.url }); res.end(); }).listen(80); // HTTPS 服务器 const options = { key: fs.readFileSync('/path/to/your_domain.key'), cert: fs.readFileSync('/path/to/fullchain.crt') }; https.createServer(options, (req, res) => { res.writeHead(200); res.end('Hello HTTPS!'); }).listen(443);

Best Practices

  • Use environment variables to store certificate paths
  • Set correct file permissions
  • Use complete certificate chain
  • Only enable TLS 1.2 and TLS 1.3
  • Configure strong cipher suites
  • Use HTTP/2 (Node.js 8.4+)
  • Configure HSTS header
  • Regularly update Node.js and dependencies
  • Monitor certificate expiration
  • Use process manager (such as PM2) to manage HTTPS service
  • Production Environment Configuration Example (Node.js 18+)

    const https = require('https'); const fs = require('fs'); const express = require('express'); const app = express(); // // Security headers setupapp.use((req, res, next) => { res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('X-XSS-Protection', '1; mode=block'); next(); }); app.get('/', (req, res) => { res.send('Hello HTTPS!'); }); const options = { key: fs.readFileSync(process.env.SSL_KEY_PATH || '/etc/ssl/private/your_domain.key'), cert: fs.readFileSync(process.env.SSL_CERT_PATH || '/etc/ssl/certs/fullchain.crt'), minVersion: 'TLSv1.2', maxVersion: 'TLSv1.3', ciphers: [ 'TLS_AES_256_GCM_SHA384', 'TLS_AES_128_GCM_SHA256', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-RSA-CHACHA20-POLY1305' ].join(':'), honorCipherOrder: true }; https.createServer(options, app).listen(443, () => { console.log('HTTPS server running on port 443'); });
    📝 Notes:
    • Use environment variables to store sensitive paths, improve security
    • Configure security response headers, enhance security
    • Using standard port 443 requires root privileges or port forwarding configuration
    • Recommend using reverse proxy (Nginx) to handle SSL, Node.js handles application logic

    Troubleshooting

    Problem 1: Certificate File Read Error

    Error: Error: Error: ENOENT: no such file or directory

    Solution:

    1. Check if certificate file path is correct (use absolute path)
    2. Confirm if file exists
    3. Check file permissions (private key file should be 600)
    4. Verify if file format is correct (PEM format)

    Problem 3: Port Conflict

    Error: Error: Error: listen EADDRINUSE: address already in use :::443

    Solution:

    1. Check if port is occupied by other process
    2. Modify port number or stop process occupying the port
    3. Stop process occupying the port
    4. Use reverse proxy (Nginx) to handle SSL, Node.js uses other port

    Problem 2: TLS Handshake Failed

    Error: Error: Error: SSL routines:ssl3_read_bytes:sslv3 alert handshake failure

    Solution:

    1. Check if certificate chain is complete
    2. Verify if certificate has expired
    3. Confirm ca option is configured correctly (if used)
    4. Check cipher suite configuration
    5. Verify if private key and certificate match

    Problem 4: Insufficient Permissions

    Error: Error: Error: listen EACCES: permission denied

    Solution:

    1. Using port 443 requires root privileges (not recommended to run directly)
    2. Use reverse proxy (Nginx) to handle SSL, Node.js uses non-privileged port
    3. Use setcap to set permissions for Node.js binary file (Linux)
    4. Use port forwarding (iptables) to forward 443 to application port

    Problem 5: Incomplete Certificate Chain

    Solution: Problem: Browser shows certificate warning, indicating incomplete certificate chain

    Solution:

    1. Ensure intermediate certificate is included: cat your_domain.crt intermediate.crt > fullchain.crt
    2. Use ca option in configuration to include intermediate certificate
    3. Verify certificate chain: openssl verify -CAfile fullchain.crt your_domain.crt