Все руководства по развёртыванию Развёртывание

Как использовать SSL-сертификаты с Node.js

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();
// ... ваши маршруты

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);

Рекомендация для продакшена: обратный прокси

Для продакшена не завершайте TLS непосредственно в Node.js. Используйте обратный прокси (Nginx, Caddy или балансировщик нагрузки) перед приложением:

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

Причины:

  • Nginx обрабатывает TLS эффективнее (C против JavaScript)
  • Обновление сертификатов не требует перезапуска Node.js
  • Порт 443 требует прав root — Node.js не должен работать от root
  • Ограничение скорости, кеширование, сжатие обрабатываются прокси
  • HTTP/2 поддержка более зрелая в Nginx

Прямой HTTPS в Node.js подходит для разработки, внутренних сервисов или небольших проектов.

Популярные фреймворки

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 / другие фреймворки (dev-серверы)

Dev-серверы фреймворков обычно имеют флаг --https для локальной разработки. Для продакшена всегда используйте обратный прокси — эти фреймворки раздают статические файлы или выполняют SSR за Nginx, Caddy или облачным балансировщиком нагрузки.

Паттерн с переменными окружения

Не хардкодьте пути к сертификатам. Используйте переменные окружения, чтобы один и тот же код работал в среде разработки и продакшена:

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);

Это перечитывает файлы при каждом новом соединении. Для лучшей производительности добавьте отслеживание файлов, чтобы перезагружать их только при изменении.

Часто задаваемые вопросы

Обрабатывать SSL в Node.js или использовать обратный прокси?

Для продакшена: используйте обратный прокси. Для разработки, небольших проектов или внутренних сервисов: прямой HTTPS в Node.js вполне подходит. Паттерн с обратным прокси является стандартным, поскольку разделяет ответственности и обрабатывает TLS более эффективно.

Можно ли использовать сертификаты GetHTTPS с Node.js?

Да. GetHTTPS создаёт стандартные PEM-файлы (privkey.pem, fullchain.pem), которые Node.js читает напрямую через fs.readFileSync().

Как обрабатывать обновление сертификатов в Node.js?

Если используется обратный прокси, просто замените файлы и перезагрузите прокси — Node.js не нужно перезапускать. Если TLS обрабатывается напрямую, используйте подход с SNICallback, описанный выше, или перезапустите процесс Node.js после замены файлов сертификатов.

А как насчёт SSL для localhost при разработке?

Используйте самоподписанный сертификат (показан выше) или mkcert для получения локально доверенного сертификата разработки. Не используйте Let’s Encrypt для localhost — он не может подтвердить домен, который недоступен публично.

Можно ли использовать сертификаты GetHTTPS с Deno или Bun?

Да. И Deno, и Bun поддерживают TLS с PEM-файлами:

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"); },
});

Одни и те же PEM-файлы от GetHTTPS работают во всех средах выполнения JavaScript.

Похожие статьи

Начало работы 2026-05-08
Как получить бесплатный SSL-сертификат (пошаговое руководство)
Получите бесплатный SSL-сертификат от Let's Encrypt за 5 минут --- без установки программ, без создания аккаунта. Полное руководство: 4 метода, оба типа проверки, установка на 6 платформах и устранение неполадок.
Развёртывание 2026-05-08
SSL-сертификаты с Docker и обратными прокси
Настройка HTTPS для Docker-контейнеров с помощью обратного прокси Nginx, Traefik с автоматическим Let's Encrypt или ручного монтирования сертификатов.
SSL и сертификаты 2026-05-07
Форматы SSL-сертификатов: PEM, PFX, DER -- подробное объяснение
Разберитесь в форматах сертификатов PEM, PFX/PKCS#12 и DER. Узнайте, какой формат нужен вашему серверу и как конвертировать между ними с помощью OpenSSL.
Получите бесплатный SSL-сертификат в браузере
Без установки, без аккаунта. Ваш приватный ключ никогда не покидает устройство.
Получить сертификат