Введение: от локального сервера к production-готовому решению
Вы создали мощное JavaScript-приложение на Node.js, протестировали его локально, и теперь настало время показать его миру. Просто залить файлы на VPS и запустить node app.js — это путь новичка. На продвинутом уровне деплой включает в себя настройку обратного прокси-сервера, менеджера процессов, автоматическое продление SSL-сертификатов, систему непрерывной интеграции и доставки (CI/CD), а также грамотный мониторинг и логирование.
В этой статье мы разберем пошаговый процесс деплоя Node.js приложения на VPS (Ubuntu 22.04) на продвинутом уровне. Мы настроим Nginx как reverse proxy, PM2 для управления процессом, Let's Encrypt для HTTPS, GitHub Actions для автоматического деплоя при пуше в репозиторий, и добавим базовый мониторинг.
Предварительные требования
- VPS сервер (Ubuntu 22.04) с доступом по SSH.
- Домен, привязанный к IP вашего сервера (например,
myapp.example.com). - Установленный Node.js (v18+) и npm на сервере.
- Git, установленный на сервере.
- Репозиторий вашего приложения на GitHub.
1. Настройка сервера и менеджера процессов PM2
Начнем с базовой подготовки окружения. После подключения к серверу по SSH, обновим пакеты и установим необходимые утилиты:
sudo apt update && sudo apt upgrade -y
sudo apt install nginx git curl -y
Убедимся, что Node.js установлен. Если нет — установим через NodeSource:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v
Теперь установим глобально PM2 — продвинутый менеджер процессов для Node.js, который автоматически перезапускает приложение при падении, управляет логами и кластеризацией:
sudo npm install -g pm2
Клонируем репозиторий вашего приложения и устанавливаем зависимости:
git clone https://github.com/ваш-username/ваш-репозиторий.git /var/www/myapp
cd /var/www/myapp
npm install --production
Создадим файл экосистемы PM2 (ecosystem.config.js) для тонкой настройки:
// ecosystem.config.js
module.exports = {
apps: [{
name: 'myapp',
script: 'app.js', // или server.js
instances: 'max', // используем все ядра CPU
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: '/var/log/node-app/err.log',
out_file: '/var/log/node-app/out.log',
log_date_format: 'YYYY-MM-DD HH:mm Z'
}]
};
Создадим директорию для логов и запустим приложение через PM2:
sudo mkdir -p /var/log/node-app
sudo chown -R $USER:$USER /var/log/node-app
pm2 start ecosystem.config.js
pm2 save
pm2 startup systemd
Команда pm2 startup создаст systemd-сервис, который будет запускать PM2 при старте системы. Теперь ваше приложение работает на порту 3000, но доступ к нему напрямую небезопасен. Переходим к настройке Nginx.
2. Настройка Nginx как reverse proxy и SSL через Let's Encrypt
Nginx будет принимать входящие запросы на порты 80 (HTTP) и 443 (HTTPS), проксировать их на ваш Node.js процесс, работающий на порту 3000, а также обслуживать статические файлы напрямую — это снижает нагрузку на Node.js.
Создадим конфигурационный файл для нашего домена:
sudo nano /etc/nginx/sites-available/myapp
Вставьте следующую конфигурацию (замените myapp.example.com на ваш домен):
server {
listen 80;
server_name myapp.example.com;
return 301 https://$server_name$request_uri; # редирект на HTTPS
}
server {
listen 443 ssl http2;
server_name myapp.example.com;
# SSL сертификаты (пока закомментированы, включим позже)
# ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# Статические файлы лучше отдавать через Nginx
location /static/ {
alias /var/www/myapp/public/;
expires 30d;
add_header Cache-Control "public, immutable";
}
access_log /var/log/nginx/myapp_access.log;
error_log /var/log/nginx/myapp_error.log;
}
Включим сайт и проверим конфигурацию:
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Теперь настроим SSL сертификат через Certbot (Let's Encrypt). Установите Certbot:
sudo apt install certbot python3-certbot-nginx -y
Запустите получение сертификата (убедитесь, что домен указывает на ваш сервер и порт 80 открыт):
sudo certbot --nginx -d myapp.example.com
Certbot автоматически изменит конфигурацию Nginx, добавив секцию SSL. После этого раскомментируйте строки с ssl_certificate в вашем конфиге (если они остались закомментированными) и перезагрузите Nginx. Настройте автообновление сертификатов:
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer