Настройка NGINX + NodeJS на Ubuntu Server
Используемые термины: NGINX, NodeJS.
Приложение NodeJS может запускаться в качестве веб-сервера и самостоятельно отвечать на http-запросы. Но в связки с NGINX его работу можно сделать быстрее и надежнее. Мы рассмотрим установку всех необходимых компонентов, настройку запуска приложения NodeJS в качестве сервиса systemd, а также приведем пример развертывания типового приложения. В инструкции используются:
- NodeJS.
- Веб-сервер NGINX.
- Операционная система Ubuntu Server.
Все действия будут пошаговыми — сначала мы развернем сервис на NodeJS, затем подключим NGINX и, на конец, рассмотрим установку веб-приложения.
Устанавливаем NodeJS
Первый запуск тестового приложения
Настройка автозапуска
Установка NGINX и настройка проксирования на Node
Чистка системы от лишнего
Пример установки типового приложения
Установка NodeJS
Установка может быть выполнена из штатного репозитория или из репозитория NodeJS. Второй вариант требует дополнительной настройки, но позволяет установить самую свежую версию пакета.
Нативная версия
Мы можем посмотреть, какая будет установлена версия следующей командой:
apt search --names-only '^nodejs$'
Мы можем увидеть что-то на подобие:
nodejs/jammy 12.22.9~dfsg-1ubuntu3 amd64
evented I/O for V8 javascript - runtime executable
* в данном примере будет устанавливаться версия 12.
Если версия из репозитория нас устраивает, то выполняем установку:
apt install nodejs
Репозиторий NodeJS
Однако, во встроенном репозитории версия NodeJS может быть очень старой, и наше приложение может работать неправильно. Для продуктивной среды необходимо уточнить у разработчика, какая версия нужна и установить ее.
Чтобы получить другую версию NodeJS, установим curl:
apt install curl
На сайте NodeJS изучим доступные версии. Предположим, нам нужна LTS версии 20. Для удобства, создадим переменную с этим значением:
export NODE_VER=20
Теперь настроим репозиторий:
curl -sL https://deb.nodesource.com/setup_${NODE_VER}.x | sudo bash -
* в данном примере мы настроим репозиторий для 20-й версии приложения.
Теперь можно установить пакет nodejs нужной нам версии:
apt install nodejs
А для установки конкретной версии, просто указываем ее в названии пакета, например:
apt install nodejs=20.11.1
Установка завершена. Проверить запуск и посмотреть версию можно командой:
node -v
Можно переходить к первому запуску тестового веб-приложения.
Запуск тестового приложения NodeJS
Для примера мы напишем маленькое веб-приложение, которое будет запускаться на порту 3000 и выводить на экран «Hello, world!».
Создаем каталог, где предполагаем хранить файлы нашего приложения:
mkdir -p /var/www/app01
Создадим файл:
vi /var/www/app01/server.js
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {
'Content-Type': 'text/plain; charset=UTF-8'
});
res.end('Hello, world!');
});
server.listen(3000, '0.0.0.0', () => {
console.log('Start NodeJS Server on http://0.0.0.0:3000/');
});
Если в нашей системе используется брандмауэр, откроем порт 3000:
iptables -I INPUT -p tcp --dport 3000 -j ACCEPT
Запустим приложение:
node /var/www/app01/server.js
На экране должно появиться:
Start NodeJS Server on http://0.0.0.0:3000/
Открываем браузер на любом компьютере в сети и переходим по адресу http://<IP-адрес сервер>:3000 — мы должны увидеть:
Наше приложение работает. Идем дальше.
Настройка автозапуска
Мы запустили вручную наше приложение. Давайте теперь настроим его автозапуск. Рассмотрим два варианта — с помощью pm2 и systemd.
pm2
Устанавливаем pm2:
npm install -g pm2
Теперь, перейдя в каталог приложения, можно его запустить командой:
cd /var/www/app01
pm2 server.js
systemd
Если нам не подходит pm2 для управления запуском приложений nodejs, можно использовать systemd. Для этого мы создадим юнит с @ — это позволит передавать имя приложения и папку при запуске.
И так, прерываем работу нашего приложения, которое мы запустили на предыдущем шаге (CTRL + C) и создаем файл:
vi /etc/systemd/system/node@.service
[Unit]
Description=NodeJS Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/node ./server.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
WorkingDirectory=/var/www/%i
[Install]
WantedBy=multi-user.target
* обратите внимание на %i — это переменная, которой мы будем передавать имя нашего приложения, которое соответствует названию каталога, где оно лежит.
Перечитываем конфигурацию systemd:
systemctl daemon-reload
Разрешаем и запускаем наше приложение:
systemctl enable node@app01 --now
* снова повторимся. app01 — имя приложения в нашем примере и ему соответствует каталог /var/www/app01.
Посмотреть состояние службы можно командой:
systemctl status node@app01
Переходим по адресу http://<IP-адрес сервер>:3000 — мы, снова, должны увидеть:
Наше приложение запускается как сервис.
Установка и настройка NGINX
Приступим к добавлению веб-сервера nginx. Его можно установить из репозитория командой:
apt install nginx
Сразу разрешим автозапуск:
systemctl enable nginx
Разрешим 80 порт в брандмауэре (если в нашей системе он используется):
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
В продуктивной среде также нужно открыть и использвать https:
iptables -I INPUT -p tcp --dport 443 -j ACCEPT
Для сохранения правил лучше всего использовать iptables-persistent:
apt install iptables-persistent
netfilter-persistent save
Переходим по адресу http://<IP-адрес сервер> (без указания порта) — мы увидим приветствие от веб-сервера:
Открываем файл:
vi /etc/nginx/sites-enabled/default
В разделе location внесем изменения, приведя его к виду:
...
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
...
* в нашем примере мы упростили настройку, чтобы сосредоточиться на связке NGINX + NodeJS. В продуктивной среде стоит использовать виртуальные домены. Подробнее про настройку полноценного веб-сервера можно почитать в инструкции Как настроить полноценный веб-сервер на Ubuntu.
Проверяем корректность настройки nginx:
nginx -t
Мы должны получить что-то на подобие:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Перезапускаем веб-сервер:
systemctl reload nginx
Переходим по адресу http://<IP-адрес сервер> (без порта 3000) и видим:
Наше приложение открывается через nginx.
Удаляем лишнее
1. Так как мы настроили запросы через nginx, нужно поменять некоторые настройки. Открываем файл:
vi /var/www/app01/server.js
Находим строки:
server.listen(3000, '0.0.0.0', () => {
console.log('Start NodeJS Server on http://0.0.0.0:3000/');
});
И меняем их на:
server.listen(3000, '127.0.0.1', () => {
console.log('Start NodeJS Server on http://127.0.0.1:3000/');
});
* мы поменяли 0.0.0.0 на 127.0.0.1, чтобы наш сервер не слушал на всех интерфейсах — нам достаточно только локальной петли. Это более безопасный вариант работы.
Перезапустим наше приложение node:
systemctl restart node@app01
Проверим, что наше приложение слушает на порту 3000 и уже на адресе 127.0.0.1:
ss -tunlp | grep :3000
Мы должны увидеть:
tcp LISTEN 0 128 127.0.0.1:3000 0.0.0.0:* users:(("node",pid=2503,fd=10))
2. Теперь удалим лишнее правило в брандмауэре (открытый порт 3000, если мы его создавали). Смотрим список добавленных правил:
iptables -L --line-numbers
Находим правило с открытым портом 3000:
2 ACCEPT tcp -- anywhere anywhere tcp dpt:3000
* в данном примере оно имеет порядковый номер 2.
Удалим его:
iptables -D INPUT 2
Сохраним правила:
apt install iptables-persistent
netfilter-persistent save
Установка приложения
В установке приложений есть множество нюансов, но мы опишем типовой подход.
Нам нужен будет менеджер пакетов node. Ставим его командой:
apt install npm
Получаем проект от разработчика и копируем его в наш каталог app01. После переходим в каталог:
cd /var/www/app01/
Как правило, разработчик поставляет приложение с файлом package.json. В этом файле описаны пакеты, необходимые для работы приложения. Установим их:
npm install
npm прочитает файл package.json и выполнит установку — после в нашем каталоге с приложением появятся папка node_modules и файл package-lock.json.
Также обратите внимание, что файл для запуска сервиса node может иметь другое имя. Уточните это у разработчика и, при необходимости, отредактируйте systemd.
Готово. Наше приложение должно работать.