- Setup Node.js Application with PM2 and NGINX
- Installing NGINX and Node.js
- Setup NGINX
- Setup PM2
- Настройка Nginx и SSL с Node.js
- Установка Nginx
- Установка на Mac
- Установка на Ubuntu
- Установка на Windows
- Настройка сервера Node.js
- Настройка SSL
- Нужен ли nginx для node.js сервера?
- 3 ответа 3
- tomasevich / nginx_nodejs.md
Setup Node.js Application with PM2 and NGINX
I’m annoying every time when I setup Basic or Demo Node.js Application, I have to Create Droplet, Install NGINX, Install Node.js and setup NGINX to be as a reverse proxy for my node application.
I want to reduce my process. It’s better if all tasks running automate. After I thought I have 2 ways:
- Create bash/shell script to install dependencies, setup NGINX and run Node.js as daemon service. when I want to setup Basic/Demo App, just run script as User Data when creating a new droplet or via Image and everything is working perfectly.
- Create docker file Only Dockerfilefile, Lucky Digital Ocean provides One-Click Application for Docker, I can create a droplet with Docker within a minute.
and for this blog post, I choose the method 1.
Installing NGINX and Node.js
Today I am going to share you about how I setup Node.js Application to up and running on Production.
After droplet was created, I install NGINX, Node.js and utility modules. ( g++ and node-gyp It’s optional, It’s required when you run some Node library that compiles to binary or depends on machine environment e.g. bcrypt, SASS, etc.
Setup NGINX
After NGINX installed, I create another NGINX config file, because of the default nginx.conf have a script to include all files that match pattern *.conf like this:
That’s mean I can create new file e.g. my-app.conf inside /etc/nginx/conf.d and everything works perfectly! and my file my-app.conf have only server name, port and match location that set proxy_pass to port that my Node is running (In my case I use port 5555)
Just restart NGINX and every is working!
Setup PM2
When you want to long run Node.js, you need daemon process, and lucky Node.js has PM2 that can able to do for you, just Install PM2 via global
Start PM2 is very easy! just go to Node.js project and run a command:
I save PM2 process for when a machine wasrestart, PM2 can running the same configuration
Настройка Nginx и SSL с Node.js
Nginx — это высокопроизводительный HTTP-сервер, а также обратный прокси-сервер. В отличие от традиционных серверов, Nginx использует асинхронную архитектуру, управляемую событиями. В результате объем памяти невелик, а производительность высока. Если вы используете веб-приложение на базе Node.js, вам следует серьезно рассмотреть возможность использования Nginx в качестве обратного прокси-сервера. Nginx может быть очень эффективным в обслуживании статических ресурсов. Для всех других запросов он будет обращаться к вашему бэкэнду Node.js и отправлять ответ клиенту. В этом уроке мы обсудим, как настроить Nginx для работы с Node.js. Мы также увидим, как настроить SSL на сервере Nginx.
Установка Nginx
Если на вашем компьютере уже установлен Node.js, давайте посмотрим, как установить Nginx.
Установка на Mac
Если вы работаете на Mac, вы можете использовать Homebrew для простой установки Nginx. Шаги следующие:
- Для homebrew необходим каталог /usr/local который нужно chown для вашего имени пользователя. Итак, сначала запустите следующую команду в терминале:
- Теперь следующие две команды установят Nginx в вашей системе.
- После завершения установки вы можете ввести следующую команду для запуска Nginx:
- Файл конфигурации Nginx можно найти здесь: /usr/local/etc/nginx/nginx.conf .
Установка на Ubuntu
Если вы используете Ubuntu, вы можете использовать следующую команду для установки Nginx:
После установки Nginx он запустится автоматически.
Установка на Windows
Для Windows зайдите на страницу загрузок Nginx и получите zip. Следующим шагом является разархивирование архива и перемещение в каталог в командной строке следующим образом:
Как видите, команда start nginx запустит Nginx.
Теперь, когда установка завершена, давайте посмотрим, как вы можете настроить простой сервер.
Настройка сервера Node.js
Сначала давайте создадим простой сервер Node.js. Если вы хотите, вы можете скачать простое приложение на основе Express здесь . Получив код, распакуйте его и перейдите в каталог demoApp на вашем терминале. Затем введите следующие команды, чтобы запустить сервер на порту 3000.
Если вы хотите, вы можете перейти непосредственно в каталог и открыть файл конфигурации в вашем любимом текстовом редакторе. При прокрутке вниз вы найдете блок server . Это выглядит примерно так:
Далее мы настроим блок сервера в соответствии с нашими потребностями. Мы хотим обслуживать статические файлы с нашего веб-сайта с помощью Nginx и передавать все остальные запросы в наш сервер Node.js. Итак, замените указанный выше блок server новым блоком, как показано ниже:
Как вы можете видеть, наш сервер Nginx прослушивает http://localhost:8080 . location / блок сообщает Nginx, что делать при поступлении любого запроса. Внутри блока location мы используем proxy_pass чтобы указать на proxy_pass Node.js, которая в нашем случае является http://localhost:3000 .
Теперь нам нужен еще один блок location /public чтобы сообщить Nginx, как обслуживать статические ресурсы. Внутри этого блока location мы устанавливаем корень в /usr/local/var/www . Вы можете выбрать другой каталог, если хотите. В результате всякий раз, когда есть запрос, такой как http://localhost:8080/public/somepath/file.html Nginx будет обслуживать файл из /usr/local/var/www/public/somepath/file.html .
На этом этапе вы должны сохранить файл и набрать следующее, чтобы перезапустить Nginx:
Mac:
Ubuntu:
Окна:
Далее, давайте подадим нашу таблицу стилей из Nginx вместо Node.js. Наш шаблон Node.js использует таблицу стилей с URL /public/stylesheets/style.css . Создайте файл с именем style.css в каталоге /usr/local/var/www/public/stylesheets и Nginx будет правильно его обслуживать. Например, вы можете поместить следующий CSS в style.css :
После этого вы можете перейти на http://localhost:8080 чтобы увидеть наше приложение в действии. Несмотря на то, что вы обращаетесь к серверу Nginx, вы получите фактический ответ от серверной части Node.js, тогда как Nginx будет обслуживать только таблицу стилей.
Настройка SSL
На производственном веб-сайте вам много раз потребуется настроить SSL для защиты конфиденциальной информации. Обычно вы идете в CA (центр сертификации) и получаете сертификат. Вы также можете создать самозаверяющий сертификат. Единственная проблема заключается в том, что браузеры будут отображать предупреждение о том, что «Сертификат не является доверенным», когда кто-то посещает ваш сайт. Но для тестирования на вашей локальной машине это прекрасно. Вот хороший учебник, который показывает, как самостоятельно подписать ваш сертификат SSL.
Получив сертификат и закрытый ключ, вы можете настроить SSL в Nginx. Вам необходимо изменить наш предыдущий блок сервера следующим образом:
Нужен ли nginx для node.js сервера?
Нужно ли ставить nginx перед нодой?
У нас в компании занимаются поиском Т-функции у новичков, и поэтому на новый проект я назначен главным backdoor разработчиком.
До этого ребята у нас ставили nginx перед нодой и имели, с моей точки зрения кучу, проблем и неявных состояний.
Например между nginx и нодой рвется ws соединения, но nginxs об этом никому ничего не говорит. А между клиентом и nginx соединение в порядке, но данные почему-то не приходят. Пришлось городить свой пинг-понг.
На мой вопрос, а зачем вам вообще nginx, мне ответили что:
1) ничто так быстро не отдает статику как nginx;
2) в конце концов все всегда так делают.
Ну статику мы отдаем клиенту 1 раз и ее не так уж много. А вот json’ы потом гоняем туда-сюда сутками, сгусями и с прочими птицами. А по поводу того, что nginx отдает статику так быстро потому, что он ее никак не обрабатывает, а видит из запроса что это «просто» статика и «просто» отдает ее (так мне объяснили) — разве написав
я не «просто» отдаю статику, никак ее не обрабатывая?
На своем проекте я пока стучусь непосредственно на ноду. Прав ли я? Рационально ли это? Или меня в будущем ждут непредвиденные трудности? На данном уровне моей квалификации мне кажется, что стучаться сразу на ноду — это само собой напрашивающийся шаг к отказу от ненужного усложнения системы и от ненужной прослойки. Действительно ли прослойка в виде nginx — ненужная?
Буду благодарен услышать Ваши комментарии.
3 ответа 3
Да, nginx добавляет сложности, требуя настроить себя, но по-моему это с лихвой компенсируется получаемыми плюшками.
Масштабируемость
Работать с одной-единственной нодой получится только до тех пор, пока на сервере находится один-единственный сайт. Однако в моей практике такого не было почти никогда: я как минимум ставлю ещё Munin для наблюдения за состоянием сервера. Придётся или вешать сайт на отдельный порт/айпишник (неудобно), или дописывать в ноде код для проксирования запросов на другой сайт (замусоривание кода всякими сложностями). В то время как в nginx новый сайт легко подключить парой строчек в конфиге.
Ещё один пример — A/B тестирование: запускаем две разные версии сайта, половину пользователей направляем на одну версию сайта, половину на другую, сравниваем их поведение и решаем, какая версия сайта лучше. Если изменения значительные, то скорее всего придётся запустить две ноды, и опять же нужно каким-то чудом решать, какой пользователь на какую ноду будет отправлен. Опять же в nginx это делается парой строчек (split_clients).
Когда сайт станет большой и популярный, нода может перестать помещаться в одном процессе или одном сервере, и придётся запускать несколько экземпляров ноды или даже докупать новые серверы. nginx позволит равномерно распределить нагрузку между процессами/серверами, принимая все запросы на себя и пересылая его на один из случайно выбранных процессов/серверов (или не случайно — смотря как настроить).
Безопасность
Использовать стандартные порты 80/443 может только root. А когда код сайта запускается от рута, это ОЧЕНЬ плохо: малейшая RCE-уязвимость — и злоумышленник без проблем получает полный доступ к серверу. Если нода будет работать от рута, то малейшая уязвимость в коде сайта может позволить с лёгкостью получить контроль над сервером целиком (как с помощью RCE, так и с помощью чтения какого-нибудь ../../../../../../etc/shadow и последующего подбора пароля от рута в оффлайне, например).
В идеале код должен быть максимально изолирован от всего (вплоть до помещения в изолированный Docker-контейнер (ходят слухи, что докер ещё и для разработки и развёртывания очень удобен, но я не верю)). Если нода будет изолирована от всех, то максимум, что получит злоумышленник — контроль над нодой. Ну и доступ к базе данных, если она используется. Это плохо, но не совсем плохо, потому что взломанную ноду можно просто выключить до исправления уязвимости. А вот выпнуть злоумышленника, получившего root, будет уже гораздо тяжелее (вплоть до необходимости отключения сервера от интернета и полной переустановки системы).
Но, допустим, вы перекостыляли с роутингом или форками или пропатчили ядро или ещё что-то и в итоге каким-то чудом умудрились поднять ноду на порту 80/443 без root. Тогда пришло время вспомнить про HTTPS и сертификаты для него. Для работы SSL/TLS ноде нужен будет доступ к приватному ключу, и опять же, если злоумышленник откопает RCE-уязвимость, то он сможет прочитать приватный ключ и начать организовывать MitM-атаки. Если же HTTPS будет настроен на nginx и доступ к приватному ключу будет только у nginx, то злоумышленник обломается. (Хотя, конечно, налажать могут всегда и везде, даже у nginx+openssl однажды утекали приватные ключи. поэтому переходим на libressl)
Кроме того, есть ряд менее серьёзных атак, которые всё же могут подпортить нервы. Например, манипуляции с медленными HTTP-запросами. В nodejs была уязвимость CVE-2013-4450, позволяющая завалить её HTTP pipelining запросами и тем самым скушать ресурсы сервера. Теоретически подобное, конечно, может найтись и в nginx, но всё же сама его архитектура неплохо спасает от подобных пакостей. При наличии nginx на ноду уже будут приходить белые и пушистые HTTP-запросы, доставляющие минимум проблем, в то время как всякий мусор будет отфильтрован или забуферизован самим nginx’ом. (Хотя от терабитных DDoS-атак ничего не спасёт, но не будем о грустном)
Прочие плюшки
Обязательно будут моменты, когда нода не будет работать (например, она может быть просто выключена на техработы). Без nginx пользователи получат просто какую-то невнятную ошибку браузера, уведомляющую о невозможности подключения. С nginx можно отдать статическую страницу с более понятным описанием ошибки и предложением сообщить о проблеме администраторам сайта, или же повесить плашку техработ и предложение подписаться на твиттер.
Про вебсокеты
Непонятно, что у вас за проблемы были — без подрбоностей понять, кто виноват и что делать, трудно; у меня всё проксируется через nginx вполне стабильно. А пинги должны быть в любом случае, потому что отвалиться по таймауту может что угодно где угодно даже не на вашем сервере (например, мобильный оператор Теле2 обрубает TCP-соединения после пяти минут бездействия). «Городить свой пинг-понг» не нужно, потому что эта фича встроена в протокол — не знаю, как именно вы реализуете вебсокеты в ноде, но пинги где-то там наверняка уже должны быть.
tomasevich / nginx_nodejs.md
Сервер в связке Nginx + NodeJs
Данная пошаговая инструкция поможет освоить основы на простом примере
Для справки
Сервер поднимался на Debian 8 c характеристиками:
CPU — 1 ядро x 500 МГц
Диск — 5 ГБ SSD+HDD
Принцип работы на пальцах
Nginx будет отдавать статические файлы самостоятельно, динамический контент передавать из NodeJS .
Установка и настройка Nginx
Представим что у вас чистый сервер и ничего не установлено. Идем в папку /root и становим Nginx :
После установки Nginx , в папке /var появилась папка /www, а в ней папка /html, а в ней файл index.html. Идем в папку /var и переименуем папку /html в папку /nginx:
Создаем доп.файл style.css (для теста):
В файле index.html пишем код, этот файл будет заглушкой:
В файле style.css пишем код:
Еще нам нуно создать папку для NodeJS :
Далее прописывем на всякий случай права для папок:
Теперь самое интересное, настраиваем файл конфига Nginx , редактируем файл default:
Очищаем весь файл и пишем (комменты # ниже):
Добавляем Nginx в автозагрузку и запускаем, что бы изменения применились, после проверяем статус:
Установка и настройка NodeJS
Идем в папку /root и под пользователем root устанавливаем cURL
С помощью cURL скачиваем NodeJS , в моем случае верся 6:
Запускаем скаченный файл:
Готово! Можно протестировать:
Вместе с NodeJS установился и NPM (Node Package Manager), с помощью которого мы установим express и pm2 :
С помощью демона pm2 можно позабыть о проблемах с падением NodeJS (устанавливаем глобально):
Инициализируем проект, создаем package.json в который будем фиксировать нужные пакеты (спасибо @niiu за подсказку)
С помощью библиотеки express код будет писаться намного проще и быстрее (устанавлиаем локально):
Создаем файл server.js для NodeJS , который будет основным (входным) файлом:
Код файла server.js описан ниже:
Теперь можно добавить демону 1 процесс и запустить наш NodeJS сервер:
При этом у нас запущен сервер Nginx
После перезагрузки ОС, pm2 сам себя не запустит и соответственно не запустит процессы. Выполняем команды:
- Сначала добавляем нужный процесс (в нашем случае скрипт NodeJS )
- Потом сохраняем конфигурацию
- После, добавляем PM2 в сервисы ОС
Если все запустилось, значит у вас ровные руки, а у меня талант писать пошаговые инструкции 🙂
Тестируем
Переходим на http://IP_адрес_сайта:80/ — дожны увидеть фразу «Тест»
Итого
Nginx является прокси-сервером, NodeJS основным приложением. Первый висит на 80 порту, второй на 8000 и слушает первый. NodeJS отдает динамику, а Nginx отвечает за статику.
Если что-то не получилось или вы нашли ошибку, пишите в комментариях ниже!