所有部署指南 部署

如何在 Node.js 中使用 SSL 證書

Node.js 透過 https 模組內建 HTTPS 支援。你載入證書檔案並建立 HTTPS 伺服器即可。本指南涵蓋原生 Node.js、Express 以及推薦的生產環境配置。

基本 HTTPS 伺服器

const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('/etc/ssl/privkey.pem'),
  cert: fs.readFileSync('/etc/ssl/fullchain.pem'),
};

https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Hello HTTPS');
}).listen(443);

Express + HTTPS

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

const app = express();

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

const options = {
  key: fs.readFileSync('/etc/ssl/privkey.pem'),
  cert: fs.readFileSync('/etc/ssl/fullchain.pem'),
};

https.createServer(options, app).listen(443, () => {
  console.log('HTTPS server running on port 443');
});

將 HTTP 重新導向到 HTTPS

同時執行 HTTP 和 HTTPS 伺服器:

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

const app = express();
// ... your routes

const options = {
  key: fs.readFileSync('/etc/ssl/privkey.pem'),
  cert: fs.readFileSync('/etc/ssl/fullchain.pem'),
};

// HTTPS server
https.createServer(options, app).listen(443);

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

生產環境建議:反向代理

在生產環境中,不要直接在 Node.js 中終結 TLS。在前面使用反向代理(NginxCaddy 或負載均衡器):

Client ──HTTPS──→ Nginx (TLS termination) ──HTTP──→ Node.js (port 3000)

原因:

  • Nginx 處理 TLS 更高效(C vs JavaScript)
  • 證書續簽不需要重啟 Node.js
  • 埠 443 需要 root 許可權 — Node.js 不應以 root 執行
  • 速率限制、快取、壓縮由代理處理
  • HTTP/2 支援在 Nginx 中更成熟

Node.js 直接 HTTPS 適合開發、內部服務或小專案。

常見框架

Fastify

const fastify = require('fastify')({
  https: {
    key: fs.readFileSync('/etc/ssl/privkey.pem'),
    cert: fs.readFileSync('/etc/ssl/fullchain.pem'),
  },
});

fastify.get('/', async () => ({ hello: 'https' }));
fastify.listen({ port: 443, host: '0.0.0.0' });

Koa

const Koa = require('koa');
const https = require('https');
const fs = require('fs');

const app = new Koa();
app.use(ctx => { ctx.body = 'Hello HTTPS'; });

https.createServer({
  key: fs.readFileSync('/etc/ssl/privkey.pem'),
  cert: fs.readFileSync('/etc/ssl/fullchain.pem'),
}, app.callback()).listen(443);

Next.js / Nuxt / 其他框架開發伺服器

框架開發伺服器通常有 --https 引數用於本地開發。生產環境中,始終使用反向代理——這些框架在 Nginx、Caddy 或雲負載均衡器後面提供靜態檔案或執行 SSR。

環境變數模式

不要硬編碼證書路徑。使用環境變數讓同一份程式碼在開發和生產環境中都能工作:

const options = process.env.SSL_KEY ? {
  key: fs.readFileSync(process.env.SSL_KEY),
  cert: fs.readFileSync(process.env.SSL_CERT),
} : null;

if (options) {
  https.createServer(options, app).listen(443);
  console.log('HTTPS server on port 443');
} else {
  app.listen(3000);
  console.log('HTTP server on port 3000 (no SSL_KEY set)');
}

使用自簽名證書進行開發

本地開發時生成自簽名證書(不用於生產):

openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
  -keyout dev-key.pem -out dev-cert.pem -days 365 -nodes \
  -subj "/CN=localhost"
const options = {
  key: fs.readFileSync('./dev-key.pem'),
  cert: fs.readFileSync('./dev-cert.pem'),
};

瀏覽器會顯示警告(自簽名證書不受信任)——開發時點選透過即可。

熱過載證書

無需重啟即可過載證書(對 Let’s Encrypt 續簽有用):

const tls = require('tls');

function loadCerts() {
  return {
    key: fs.readFileSync('/etc/ssl/privkey.pem'),
    cert: fs.readFileSync('/etc/ssl/fullchain.pem'),
  };
}

const server = https.createServer({
  SNICallback: (hostname, cb) => {
    const ctx = tls.createSecureContext(loadCerts());
    cb(null, ctx);
  },
}, app);

這會在每個新連線時重新讀取檔案。為了更好的效能,新增一個檔案監聽器,僅在檔案變化時過載。

常見問題

應該在 Node.js 中處理 SSL 還是用反向代理?

生產環境:用反向代理。開發、小專案或內部服務:Node.js 直接 HTTPS 沒問題。反向代理模式是標準做法,因為它分離了關注點並更高效地處理 TLS。

可以在 Node.js 中使用 GetHTTPS 證書嗎?

可以。GetHTTPS 生成標準 PEM 檔案(privkey.pemfullchain.pem),Node.js 透過 fs.readFileSync() 直接讀取。

如何在 Node.js 中處理證書續簽?

如果使用反向代理,只需替換檔案並重新載入代理——Node.js 不需要重啟。如果直接處理 TLS,使用上面的 SNICallback 方法或在替換證書檔案後重啟 Node.js 程序。

localhost 開發的 SSL 怎麼處理?

使用自簽名證書(如上所示)或 mkcert 獲取本地信任的開發證書。不要為 localhost 使用 Let’s Encrypt——它無法驗證非公開可訪問的域名。

可以在 Deno 或 Bun 中使用 GetHTTPS 證書嗎?

可以。Deno 和 Bun 都支援 PEM 檔案的 TLS:

Deno:

Deno.serve({
  port: 443,
  cert: Deno.readTextFileSync("/etc/ssl/fullchain.pem"),
  key: Deno.readTextFileSync("/etc/ssl/privkey.pem"),
}, (req) => new Response("Hello HTTPS"));

Bun:

Bun.serve({
  port: 443,
  tls: {
    cert: Bun.file("/etc/ssl/fullchain.pem"),
    key: Bun.file("/etc/ssl/privkey.pem"),
  },
  fetch(req) { return new Response("Hello HTTPS"); },
});

來自 GetHTTPS 的同一份 PEM 檔案適用於所有 JavaScript 執行時。

相關文章

快速開始 2026-05-08
如何獲取免費 SSL 證書(分步指南)
5 分鐘從 Let's Encrypt 獲取免費 SSL 證書 — 無需安裝軟體、無需註冊賬號。涵蓋 4 種方法、兩種驗證方式、6 個平臺的安裝教程和故障排除。
部署 2026-05-08
Docker 與反向代理的 SSL 證書配置
為 Docker 容器配置 HTTPS:使用 Nginx 反向代理、Traefik 自動獲取 Let's Encrypt 證書,或手動掛載證書。
SSL 與憑證 2026-05-07
SSL 證書格式:PEM、PFX、DER 詳解
理解 PEM、PFX/PKCS#12 和 DER 證書格式。瞭解你的伺服器需要哪種格式,以及如何使用 OpenSSL 在它們之間轉換。
在瀏覽器中取得免費 SSL 憑證
無需安裝,無需帳號。私鑰始終留在你的裝置上。
取得憑證