Как настроить приложение Node.js для работы в производственном режиме на Rocky Linux 9

Введение

Node.js – это среда выполнения JavaScript с открытым исходным кодом для создания серверных и сетевых приложений. Платформа работает на Linux, macOS, FreeBSD и Windows. Хотя вы можете запускать приложения Node.js из командной строки, этот учебник сосредоточен на их запуске в качестве службы. Это означает, что они будут перезапускаться при перезагрузке или сбое и безопасны для использования в производственной среде.

В этом учебнике вы настроите готовую к использованию в производстве среду Node.js на одном сервере с Rocky Linux 9. На этом сервере будет запущено приложение Node.js, управляемое PM2, и предоставлен безопасный доступ пользователям к приложению через обратный прокси Nginx. Сервер Nginx будет предлагать HTTPS с использованием бесплатного сертификата, предоставленного Let’s Encrypt.

Предварительные требования

Это руководство предполагает, что у вас есть следующее:

Когда вы завершите предварительные требования, у вас будет сервер, обслуживающий страницу-заполнитель по умолчанию вашего домена по адресу https://example.com/.

Шаг 1 — Создание приложения Node.js

Давайте напишем приложение Hello World, которое возвращает “Hello World” на любые HTTP-запросы. Это примерное приложение поможет вам начать работу с Node.js. Вы можете заменить его на свое собственное приложение — просто убедитесь, что вы модифицировали ваше приложение для прослушивания соответствующих IP-адресов и портов.

Текстовый редактор по умолчанию, поставляемый с Rocky Linux 9, – vi. vi – это чрезвычайно мощный текстовый редактор, но он может быть несколько сложным для пользователей без опыта работы с ним. Вам может понадобиться установить более удобный для пользователя редактор, такой как nano, чтобы облегчить редактирование файлов конфигурации на вашем сервере Rocky Linux 9:

  1. sudo dnf install nano

Теперь, используя nano или ваш текстовый редактор по умолчанию, создайте образец приложения с именем hello.js:

  1. nano hello.js

Вставьте следующий код в файл:

~/hello.js
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Сохраните файл и выйдите из редактора. Если вы используете nano, нажмите Ctrl+X, затем, когда будет предложено, введите Y, а затем нажмите Enter.

Это приложение Node.js слушает указанный адрес (localhost) и порт (3000), и возвращает “Hello World!” с HTTP-кодом успеха 200. Поскольку мы слушаем localhost, удаленные клиенты не смогут подключиться к нашему приложению.

Чтобы проверить ваше приложение, введите:

  1. node hello.js

Вы получите следующий вывод:

Output
Server running at http://localhost:3000/

Примечание: Запуск приложения Node.js таким образом заблокирует выполнение дополнительных команд до тех пор, пока приложение не будет завершено, нажав CTRL+C.

Чтобы протестировать приложение, откройте другую сессию терминала на вашем сервере и подключитесь к localhost с помощью curl:

  1. curl http://localhost:3000

Если вы получите следующий вывод, приложение работает правильно и слушает правильный адрес и порт:

Output
Hello World!

Если вы не получите ожидаемый вывод, убедитесь, что ваше приложение Node.js запущено и настроено на прослушивание правильного адреса и порта.

Как только вы убедитесь, что все работает, завершите выполнение приложения (если вы еще этого не сделали), нажав CTRL+C.

Шаг 2 — Установка PM2

Теперь давайте установим PM2, менеджер процессов для приложений на Node.js. PM2 позволяет демонизировать приложения, чтобы они запускались в фоновом режиме как служба.

Используйте npm, чтобы установить последнюю версию PM2 на вашем сервере:

  1. sudo npm install pm2@latest -g

Опция -g указывает npm установить модуль глобально, чтобы он был доступен системно.

Давайте сначала воспользуемся командой pm2 start, чтобы запустить ваше приложение, hello.js, в фоновом режиме:

  1. pm2 start hello.js

Это также добавляет ваше приложение в список процессов PM2, который выводится каждый раз при запуске приложения:

Output
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Как указано выше, PM2 автоматически присваивает Имя приложения (на основе имени файла, без расширения .js) и идентификатор PM2. PM2 также сохраняет другую информацию, такую как PID процесса, его текущий статус и использование памяти.

Приложения, запущенные под управлением PM2, будут автоматически перезапускаться, если приложение выйдет из строя или будет завершено, но мы можем предпринять дополнительные шаги, чтобы приложение запускалось при загрузке системы, используя подкоманду startup. Эта подкоманда создает и настраивает скрипт запуска для запуска PM2 и управляемых им процессов при загрузке сервера:

  1. pm2 startup systemd
Output
… [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Скопируйте и выполните предоставленную команду (это сделано для избежания проблем с разрешениями при запуске инструментов Node.js от имени sudo):

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output
… [ 'systemctl enable pm2-sammy' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-sammy... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 unstartup systemd

Теперь вам потребуется внести изменение в службу системы, которая была только что сгенерирована, чтобы сделать ее совместимой с системой безопасности SELinux Rocky Linux. С помощью nano или вашего любимого текстового редактора откройте /etc/systemd/system/pm2-sammy.service:

  1. sudo nano /etc/systemd/system/pm2-sammy.service

В блоке [Service] файла конфигурации замените содержимое параметра PIDFile на /run/pm2.pid, как показано ниже, и добавьте другую выделенную строку Environment:

/etc/systemd/system/pm2-sammy.service
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

Сохраните и закройте файл. Теперь вы создали службу systemd unit, которая запускает pm2 для вашего пользователя при загрузке. Этот экземпляр pm2, в свою очередь, запускает hello.js.

Запустите службу с помощью systemctl:

  1. sudo systemctl start pm2-sammy

Проверьте состояние службы systemd:

  1. systemctl status pm2-sammy

Для подробного обзора systemd, пожалуйста, ознакомьтесь с Основы systemd: работа с сервисами, юнитами и журналом.

Кроме того, помимо того, что мы рассмотрели, PM2 предоставляет множество подкоманд, которые позволяют управлять или получать информацию о ваших приложениях.

Остановите приложение с помощью этой команды (указав имя App name или id PM2):

  1. pm2 stop app_name_or_id

Перезапустите приложение:

  1. pm2 restart app_name_or_id

Выведите список приложений, управляемых в данный момент PM2:

  1. pm2 list

Получите информацию о конкретном приложении, используя его App name:

  1. pm2 info app_name

Мониторинг процессов PM2 можно вызвать с помощью подкоманды monit. Это отображает состояние приложения, использование ЦП и память:

  1. pm2 monit

Обратите внимание, что запуск pm2 без аргументов также отобразит справочную страницу с примерами использования.

Теперь, когда ваше приложение Node.js запущено и управляется PM2, давайте настроим обратный прокси.

Шаг 3 — Настройка Nginx в качестве обратного прокси-сервера

Ваше приложение запущено и слушает localhost, но вам нужно настроить способ доступа для ваших пользователей. Мы настроим веб-сервер Nginx в качестве обратного прокси для этой цели.

В предварительном руководстве вы настроили конфигурацию Nginx в файле /etc/nginx/conf.d/ваш_домен.conf. Откройте этот файл для редактирования:

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

Внутри блока server у вас должен быть существующий блок location /. Замените содержимое этого блока следующей конфигурацией. Если ваше приложение настроено на прослушивание другого порта, обновите выделенную часть на правильный номер порта:

/etc/nginx/conf.d/your_domain.conf
server {
...
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Это настраивает сервер для ответа на запросы в его корне. Предполагая, что наш сервер доступен по ваш_домен, обращение по адресу https://ваш_домен/ через веб-браузер отправит запрос к файлу hello.js, слушающему порт 3000 на localhost.

Вы можете добавить дополнительные блоки location в тот же блок сервера, чтобы предоставить доступ к другим приложениям на том же сервере. Например, если вы также запускаете еще одно приложение Node.js на порту 3001, вы можете добавить этот блок location, чтобы разрешить доступ к нему через https://ваш_домен/app2:

/etc/nginx/conf.d/your_domain.conf — Optional
server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Как только вы закончите добавление блоков location для ваших приложений, сохраните файл и закройте редактор.

Убедитесь, что вы не ввели синтаксические ошибки, набрав:

  1. sudo nginx -t

Перезапустите Nginx:

  1. sudo systemctl restart nginx

Предполагая, что ваше приложение Node.js работает, и ваша конфигурация приложения и Nginx корректны, вы теперь должны иметь доступ к вашему приложению через обратный прокси Nginx. Попробуйте это, обратившись к URL-адресу вашего сервера (его общедоступный IP-адрес или доменное имя).

Заключение

Поздравляю! Теперь у вас есть ваше приложение Node.js, работающее за обратным прокси Nginx на сервере Rocky Linux 9. Эта настройка обратного прокси достаточно гибкая, чтобы предоставлять вашим пользователям доступ к другим приложениям или статическому веб-контенту, который вы хотите поделиться.

После этого вам может понадобиться изучить Как создать приложение Node.js с помощью Docker.

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-rocky-linux-9