Community
55
HostiServer
2026-03-23 12:40:00

Node.js на VPS: повний гайд від установки до production у 2026

⏱️ Час читання: ~9 хвилин | 📅 Оновлено: 23 березеня 2026

Чому Node.js на VPS — і чому не shared hosting

Проблема в тому, що більшість гайдів в інтернеті закінчуються на node app.js — і все, ніби додаток готовий до production. Насправді між "запустив на localhost" та "додаток стабільно працює під навантаженням" — ціла прірва: процес-менеджер, reverse proxy, SSL, файрвол, моніторинг, захист від витоків пам'яті.

У цьому гайді — повний шлях від чистого Ubuntu-сервера до production-ready Node.js. Кожен крок з реальними конфігами та поясненнями чому саме так, а не інакше. Весь матеріал базується на рекомендаціях інженерів Hostiserver які щодня працюють з Node.js проєктами клієнтів.

Крок 1: Підготовка VPS

Перед встановленням Node.js — базове налаштування безпеки. Це займе 10 хвилин, але убереже від проблем потім. Свіжий Ubuntu VPS без цих кроків — як квартира з відчиненими дверима: рано чи пізно хтось зайде.

Щодо вибору конфігурації VPS: для невеликого API або бота достатньо 1 vCPU і 2 ГБ RAM. Для середнього проєкту з PM2 Cluster Mode, Redis та Nginx — рекомендуємо від 2 vCPU і 4 ГБ. NVMe диск обов'язковий якщо використовуєте Redis або маєте інтенсивне логування — різниця з HDD при випадковому читанні/записі колосальна.

Оновлення системи

Перше що робимо на будь-якому новому сервері — оновлюємо пакети. Стара версія OpenSSL чи ядра — це відомі вразливості які експлуатуються автоматичними сканерами:

sudo apt update && sudo apt upgrade -y

Створення окремого користувача

Ніколи не запускайте Node.js від root. Створіть окремого користувача з обмеженими правами:

sudo adduser nodeapp
sudo usermod -aG sudo nodeapp
su - nodeapp

Налаштування файрволу (UFW)

Ubuntu має вбудований UFW (Uncomplicated Firewall), але за замовчуванням він вимкнений. Включаємо і відкриваємо тільки три порти — SSH для управління, 80 для HTTP та 443 для HTTPS:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Після активації перевірте статус командою sudo ufw status — в списку повинні бути тільки ці три правила. Все інше заблоковано автоматично.

⚠️ Важливо: Не відкривайте порт 3000 (або інший порт додатку) назовні. Nginx буде проксувати трафік з 80/443 на ваш додаток. Прямий доступ до порту Node.js — це дірка в безпеці.

SSH-ключі замість паролів — обов'язково. Парольна автентифікація — одна з найпоширеніших причин зламу серверів через brute-force. Якщо ще не налаштували SSH-ключі — зробіть це першим ділом, навіть перед установкою Node.js. Згенеруйте пару ключів на локальній машині (ssh-keygen -t ed25519), скопіюйте публічний ключ на сервер (ssh-copy-id nodeapp@your-server-ip) та вимкніть парольну автентифікацію в /etc/ssh/sshd_config.

Крок 2: Встановлення Node.js через NVM

Забудьте apt install nodejs — ця команда дасть стару версію з репозиторію Ubuntu і створить конфлікти якщо на сервері більше одного проєкту. Проблема не тільки у версії: при оновленні через apt можуть зламатись глобальні npm-пакети, а відкотити зміни без знесення всього — складно.

Правильний спосіб — NVM (Node Version Manager). Він встановлюється у домашню директорію користувача, не потребує sudo, і дозволяє миттєво перемикатися між версіями для різних проєктів. Один VPS — два проєкти — один на Node 20, другий на Node 22 — жодних конфліктів.

Встановлення NVM

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc

Встановлення Node.js LTS

nvm install 22
nvm use 22
nvm alias default 22

У 2026 році золотий стандарт — LTS 22.x. Ця версія забезпечує баланс між новими можливостями (оновлений V8 engine, нативний Fetch API) та стабільністю для production.

Перевірка

node -v    # v22.x.x
npm -v     # 10.x.x

ℹ️ Альтернатива: Fast Node Manager (fnm) — швидша альтернатива NVM, написана на Rust. Обидва варіанти підходять для production. Головне — не використовуйте системний пакетний менеджер.

Крок 3: Деплой застосунку

Сервер готовий, Node.js встановлений — час деплоїти сам додаток. Найпростіший спосіб — через Git. Якщо у вас ще немає репозиторію — саме час створити, бо деплоїти через FTP чи scp окремі файли у 2026 році — це шлях до хаосу з версіями.

cd /home/nodeapp
git clone https://github.com/your-user/your-app.git
cd your-app
npm install --production

Прапорець --production ігнорує devDependencies — тестові фреймворки, лінтери та інструменти збірки не потрібні на production-сервері. Це економить місце та зменшує кількість потенційних вразливостей.

Якщо на VPS кілька проєктів — кожен в окремій директорії зі своїм ecosystem.config.js для PM2 та окремим конфігом Nginx. Наприклад: /home/nodeapp/api на порту 3000 і /home/nodeapp/admin на порту 3001, кожен за своїм Nginx server block.

Файл оточення (.env)

Ніколи не зберігайте паролі та ключі в коді. Створіть .env файл:

NODE_ENV=production
PORT=3000
DB_HOST=localhost
DB_PASSWORD=your_secure_password
SESSION_SECRET=random_string_here

🚨 Увага: Додайте .env у .gitignore. Якщо цей файл потрапить у Git-репозиторій — вважайте що всі паролі скомпрометовані.

Тестовий запуск

node app.js

Якщо додаток запустився без помилок і відповідає на curl http://localhost:3000 — переходимо до PM2.

Крок 4: PM2 для production

Запускати Node.js через node app.js на production — все одно що їхати без ременя безпеки. Процес впаде від першої необробленої помилки, і ніхто його не перезапустить.

PM2 — де-факто стандарт для управління Node.js процесами. Він перезапускає додаток при падінні, розподіляє навантаження по ядрах, і переживає перезавантаження сервера. Без PM2 будь-який необроблений exception зупинить ваш процес — і відновити його зможе тільки адміністратор вручну, якщо помітить проблему.

Встановлення

npm install -g pm2

ecosystem.config.js

Замість запуску через командний рядок — створіть конфігураційний файл:

module.exports = {
  apps: [{
    name: 'my-app',
    script: './app.js',
    instances: 'max',
    exec_mode: 'cluster',
    max_memory_restart: '1G',
    exp_backoff_restart_delay: 100,
    env_production: {
      NODE_ENV: 'production',
      PORT: 3000
    }
  }]
};

Що тут важливо:

  • instances: 'max' — PM2 автоматично створить по одному процесу на кожне ядро CPU. На VPS з 4 ядрами — 4 процеси, кожен обробляє запити паралельно.
  • exec_mode: 'cluster' — обов'язково. Без кластерного режиму Node.js використовує лише одне ядро, решта простоює.
  • max_memory_restart: '1G' — захист від витоків пам'яті. Якщо процес з'їв більше 1 ГБ — PM2 тихо перезапустить його без простою (решта процесів продовжують працювати).
  • exp_backoff_restart_delay — якщо додаток падає циклічно, затримка між рестартами збільшується поступово. Без цього PM2 може створити нескінченний цикл перезапусків.

Запуск та автостарт

pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup

Тепер додаток переживе перезавантаження сервера і автоматично стартує.

Корисні команди PM2

pm2 list              # Список процесів
pm2 logs my-app       # Логи в реальному часі
pm2 monit             # Моніторинг CPU/RAM
pm2 reload my-app     # Zero-downtime перезапуск

Крок 5: Nginx як reverse proxy + SSL

Node.js не повинен слухати порт 80 або 443 напряму. Це одна з найпоширеніших помилок — "а навіщо Nginx, якщо Node.js сам вміє HTTP?" Відповідь: Nginx стоїть перед Node.js і виконує задачі які Node.js робить погано або не робить взагалі.

SSL-термінація — Nginx обробляє шифрування значно ефективніше. Захист від slow loris та інших повільних атак — Node.js витратить на кожне таке з'єднання цілий тред event loop, Nginx ні. Статичні файли — Nginx віддає їх напряму з диска, не навантажуючи Node.js. Балансування — якщо PM2 запустив 4 воркери, Nginx розподілить запити між ними.

Встановлення Nginx та Certbot

Nginx — найпопулярніший reverse proxy для Node.js. Certbot від Let's Encrypt видає безкоштовні SSL-сертифікати з автоматичним оновленням кожні 90 днів:

sudo apt install nginx certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com

Certbot сам додасть SSL-рядки в конфігурацію Nginx. Перевірити що автооновлення працює можна командою sudo certbot renew --dry-run.

Конфігурація Nginx

server {
    listen 443 ssl http2;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        # Підтримка WebSockets
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_cache_bypass $http_upgrade;
        # Тайм-аути
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

💡 Порада: Зверніть увагу на рядки proxy_set_header Upgrade та Connection 'upgrade' — без них WebSocket-з'єднання (чати, нотифікації, real-time дашборди) не працюватимуть через Nginx.

Перевірка та перезапуск

sudo nginx -t
sudo systemctl reload nginx

Не забудьте також додати блок для перенаправлення HTTP → HTTPS:

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

Тепер ваш додаток доступний через HTTPS, а порт 3000 закритий файрволом від зовнішнього доступу. Замініть example.com на ваш реальний домен у всіх конфігах.

Якщо ваш додаток окрім API також віддає статичні файли (зображення, CSS, JavaScript для фронтенду) — додайте окремий location-блок щоб Nginx обслуговував їх напряму, не навантажуючи Node.js:

location /static/ {
    alias /home/nodeapp/your-app/public/;
    expires 30d;
    add_header Cache-Control "public, immutable";
}

Це значно зменшить навантаження на Node.js процеси — Nginx віддає статику з диска в десятки разів ефективніше.

Безпека Node.js на production

Файрвол та SSH-ключі — це базовий рівень. Для Node.js є додаткові вектори атак, про які забувають. npm-екосистема — це тисячі залежностей, і кожна з них потенційна точка входу. А HTTP-заголовки за замовчуванням розкривають інформацію про ваш стек яка допомагає атакуючим.

Helmet.js

Набір middleware що виставляє безпечні HTTP-заголовки. Без Helmet ваш Express-застосунок відповідає з заголовками за замовчуванням які розкривають стек технологій (наприклад, X-Powered-By: Express) і не захищають від базових атак. Helmet за одну строчку коду закриває десяток поширених вразливостей — XSS, clickjacking, MIME sniffing:

const helmet = require('helmet');
app.use(helmet());

Rate Limiting

Обмежує кількість запитів з однієї IP-адреси за проміжок часу. Без rate limiting автоматичний скрипт може надіслати тисячі запитів за секунду — перебрати паролі, спарсити контент, або просто покласти ваш API надмірним навантаженням:

const rateLimit = require('express-rate-limit');
app.use(rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 хвилин
  max: 100                     // максимум 100 запитів
}));

Для ендпоінтів авторизації встановіть окремий, жорсткіший ліміт — наприклад, 5 спроб за 15 хвилин. Для серйознішого захисту — додайте rate limiting ще й на рівні Nginx через директиву limit_req. Два рівні обмежень надійніше ніж один: Nginx відхиляє зайві запити ще до того як вони потрапляють до Node.js.

npm audit

Регулярно перевіряйте вразливості у залежностях:

npm audit
npm audit fix

Зробіть це частиною CI/CD або хоча б запускайте перед кожним деплоєм. Середній Node.js проєкт має сотні транзитивних залежностей — бібліотек які тягнуть інші бібліотеки, які тягнуть ще інші. Одна вразлива бібліотека десь на третьому рівні вкладеності може скомпрометувати весь сервер. За останні роки було кілька гучних інцидентів з npm-пакетами що крали змінні оточення — тобто паролі до баз даних та API-ключі.

⚠️ Нагадування: Node.js процес ніколи не повинен працювати від root. Окремий користувач з обмеженими правами — це не рекомендація, а вимога для production.

Оптимізація продуктивності та моніторинг

Додаток працює, Nginx проксує трафік, PM2 стежить за процесами — базова конфігурація готова. Тепер час зробити так, щоб все це працювало не просто правильно, а швидко. Три інструменти які дають найбільший приріст продуктивності: Redis для кешування, Gzip для стиснення відповідей, та правильний моніторинг щоб бачити де є вузькі місця.

Redis для кешування

Якщо ваш додаток часто ходить у базу даних з однаковими запитами — Redis кардинально змінює картину. У кейсі з eCommerce API зі вступу саме впровадження Redis для кешування важких SQL-запитів до каталогу товарів стало одним з трьох факторів що зменшили час відповіді з 850 до 120 мс.

Встановлення на Ubuntu:

sudo apt install redis-server -y
sudo systemctl enable redis-server

Принцип простий: перед запитом до бази — перевірити чи є результат в Redis. Якщо є — повернути з кешу (мікросекунди замість мілісекунд). Якщо немає — зробити запит, зберегти результат у кеш з TTL:

const Redis = require('ioredis');
const redis = new Redis();
async function getProducts(categoryId) {
  const cacheKey = `products:${categoryId}`;
  const cached = await redis.get(cacheKey);
  if (cached) return JSON.parse(cached);
  const products = await db.query(
    'SELECT * FROM products WHERE category_id = ?',
    [categoryId]
  );
  await redis.set(cacheKey, JSON.stringify(products), 'EX', 300);
  return products;
}

TTL (Time To Live) залежить від типу даних: каталог товарів — 5-15 хвилин, конфігурації — 1 година, сесії користувачів — до 24 годин. Головне правило: кешуйте те що читається часто і змінюється рідко.

Один нюанс про який часто забувають — інвалідація кешу. Коли адміністратор оновлює ціну товару, старий кеш повинен бути видалений. Найпростіший підхід — при зміні даних видаляти відповідний ключ: await redis.del('products:' + categoryId). Наступний запит піде напряму в базу і оновить кеш свіжими даними.

Gzip стиснення через Nginx

Якщо ваш API повертає JSON — а більшість Node.js API саме так і роблять — Gzip стиснення зменшує обсяг трафіку в 5–10 разів. Це особливо помітно на мобільних з'єднаннях і при великих масивах даних. Додайте в секцію http головного конфігу Nginx (/etc/nginx/nginx.conf):

gzip on;
gzip_types application/json text/plain application/javascript;
gzip_min_length 1000;

Параметр gzip_min_length означає що Nginx не буде стискати відповіді менше 1000 байт — для дрібних відповідей overhead стиснення перевищує вигоду. Клієнти не помітять різниці — браузери та HTTP-бібліотеки автоматично розпаковують Gzip.

Zero-downtime деплой оновлень

Коли потрібно оновити код на production — не зупиняйте весь сервіс. PM2 у cluster mode підтримує команду reload, яка перезапускає процеси по одному. Поки один воркер перезавантажується з новим кодом, інші продовжують обробляти запити:

cd /home/nodeapp/your-app
git pull origin main
npm install --production
pm2 reload my-app

Користувачі нічого не помітять. Для більших проєктів варто налаштувати CI/CD пайплайн через GitHub Actions або GitLab CI — тоді деплой відбувається автоматично при пуші в main-гілку. Базовий workflow: push → автоматичний npm audit → npm test → SSH на VPS → git pull → npm install → pm2 reload. Весь цикл займає 30-60 секунд.

Моніторинг: Prometheus + Grafana

Додаток працює, але чи працює він добре? Без моніторингу ви дізнаєтесь про проблему тільки коли клієнти почнуть скаржитись — або коли PM2 перезапустить процес вже вп'яте за годину. Event Loop Lag поступово росте, пам'ять тече, з'єднання до бази не закриваються — все це невидимо без інструментів спостереження.

Найкраща зв'язка для production-моніторингу Node.js — Prometheus + Grafana. Prometheus збирає метрики з вашого додатку через спеціальний ендпоінт (використовуйте пакет prom-client), а Grafana візуалізує їх у дашборди з алертами на email або Slack. Ключові метрики:

МетрикаЩо показуєКоли бити тривогу
Event Loop LagЗатримка обробки подій — найважливіша метрика для Node.js> 100 мс
Process CPUНавантаження на процесор кожним воркером> 80% постійно
Heap Memory UsedСпоживання пам'яті (шукайте тренд зростання — це memory leak)Постійне зростання без падінь
Active HandlesВідкриті з'єднання, файли, таймериРізке зростання

ℹ️ Бюджетна альтернатива: Якщо Prometheus + Grafana — забагато для вашого проєкту, PM2 Plus (платна версія PM2) дає базовий моніторинг з веб-дашбордом без додаткового налаштування.

Production-чекліст: перевір перед запуском

Все налаштовано, додаток працює — але перш ніж пускати реальних користувачів, пройдіться по цьому списку. Кожен пропущений пункт — це потенційний інцидент о третій ночі. Краще витратити 15 хвилин на перевірку зараз, ніж годину на відновлення потім.

💡 Чекліст Node.js production:

☐ Node.js встановлений через NVM (не apt), версія LTS 22.x
☐ Додаток запущений через PM2 у cluster mode, не через node app.js
☐ PM2 налаштований на автостарт (pm2 save + pm2 startup)
☐ Nginx reverse proxy перед Node.js з SSL через Let's Encrypt
☐ Порт додатку (3000) закритий у файрволі, відкриті тільки 80, 443, SSH
☐ Процес працює від окремого користувача, не від root
☐ Паролі, ключі та токени у .env файлі, .env у .gitignore
☐ Helmet.js підключений для безпечних HTTP-заголовків
☐ Rate limiting налаштований (на рівні додатку та/або Nginx)
☐ npm audit не показує критичних вразливостей
☐ Логування працює — pm2 logs показує що відбувається
☐ Моніторинг налаштований — ви знаєте коли щось йде не так

Якщо всі пункти виконані — ваш Node.js додаток готовий до production навантаження. Якщо ні — кожен пропущений пункт це потенційний інцидент о 3 годині ночі.

5 помилок які ламають Node.js на production

Ці помилки повторюються з проєкту в проєкт. Кожна виглядає дрібницею на етапі розробки — але на production під навантаженням перетворюється на серйозну проблему з простоєм, витоком даних або деградацією продуктивності.

ПомилкаНаслідкиРішення
Запуск від root Вразливість у додатку = повний доступ до сервера Окремий користувач з обмеженими правами
node app.js без PM2 Одна помилка — додаток мертвий, ніхто не перезапустить PM2 з cluster mode та auto-restart
Node.js слухає порт 80 напряму Немає SSL, немає захисту від slow loris, немає балансування Nginx reverse proxy перед Node.js
Паролі у коді або Git Будь-хто з доступом до репозиторію бачить credentials .env файл + .gitignore
Встановлення через apt install Стара версія, конфлікти між проєктами, складне оновлення NVM або fnm для управління версіями

Всі ці помилки об'єднує одне: вони непомітні на етапі розробки і під час тестування. Проблеми починаються тільки коли додаток потрапляє під реальне навантаження або стає ціллю автоматичних сканерів — а це питання днів, не місяців.

🚀 Готові запустити Node.js на надійному VPS?

Продуктивність вашого додатку починається з правильного сервера. NVMe диски, гарантовані ресурси, підтримка яка розуміє Node.js.

💻 Cloud (VPS) Хостинг

  • Від $19.95/міс — Починайте малим, масштабуйте миттєво
  • KVM віртуалізація — Гарантовані ресурси без overselling
  • NVMe сховище — Швидка продуктивність для Node.js
  • Root доступ — Повний контроль: NVM, PM2, Nginx — все ваше
  • 24/7 підтримка — <10 хв відповідь

🖥️ Виділені Сервери

  • Від $200/міс — Для high-load Node.js API
  • Кастомні конфігурації — Intel або AMD, до 128 ядер
  • Кілька локацій — EU + USA
  • 99.9% uptime — SLA гарантія
  • DDoS захист — Включено
  • Безкоштовна міграція — Допоможемо перенести проєкт

💬 Не впевнені який варіант вам необхідний?
💬 Напишіть нам і ми зі всім допоможемо!

Часті питання

Яку версію Node.js обрати для production у 2026?

LTS 22.x — золотий стандарт. Ця версія отримує security-патчі до квітня 2027 і підтримує всі сучасні можливості: оновлений V8 engine, нативний Fetch API, покращений ESM. Встановлюйте через NVM, не через apt.

Скільки оперативної пам'яті потрібно для Node.js на VPS?

Мінімум — 2 ГБ для невеликого додатку з PM2 та Nginx. Для API з Redis кешуванням та кількома воркерами — від 4 ГБ. Реальний eCommerce API стабільно працює на 4 ГБ з 4 PM2-процесами.

PM2 чи systemd — що краще для Node.js?

PM2 — для Node.js він зручніший. Cluster mode з балансуванням, zero-downtime reload, вбудований моніторинг, ecosystem.config.js — все це з коробки. Systemd підходить для простих сервісів, але для Node.js PM2 дає більше контролю.

Чи обов'язковий Nginx якщо Node.js сам може слухати порт 80?

Так, обов'язковий. Nginx обробляє SSL-термінацію, стиснення, статичні файли, та захищає від повільних з'єднань (slow loris). Node.js на порту 80 без Nginx — це production без захисту.

Як оновити Node.js на production без простою?

Через NVM: встановіть нову версію (nvm install 22.x), перевірте сумісність, потім pm2 reload all. PM2 у cluster mode перезапустить процеси по одному — жоден запит не буде втрачений.

Чи потрібен Redis для кожного Node.js проєкту?

Ні, не для кожного. Redis дає максимальний ефект коли додаток часто робить однакові запити до бази даних — каталоги товарів, списки категорій, конфігурації. Для простого лендінгу або API з унікальними запитами на кожен виклик Redis не додасть помітної різниці.

Contents

Поділіться цією статтею

VPS з підтримкою від

$19 95 / міс

Виділені сервери від

$80 / міс

CDN починаючи від

$0 / міс

 

Користуючись цим сайтом, ви погоджуєтеся на використання файлів cookies відповідно до нашої Політики Конфіденційності.