Запускаем Next.js приложение через PM2 на Nginx в простейшей конфигурации

Next js приложение - конф файлы

После написания нашего прекрасного веб приложения встает вопрос, как запустить его покорять мир (на рабочем сервере с доменом и прочим). Здесь нам и понадобится Nginx, тк мы хотим получить полноценный вебсервер и SSL в том числе.

Для начала стоит отметить, что без SSL для тестовых запусков достаточно и npm run start на 80 порту — все заработает из коробки, ну почти, если домен напрямую прокинут на айпишники и в нашем распоряжении целый отдельный сервер.

Схема работы

Наша схема работы будет выглядеть максимально просто:

  1. Nginx висит, как и подобает вебсерверу, на 80 и 443 портах, обеспечивая маршрутизацию и SSL;
  2. Запросы мы проксируем на localhost с нужным портом, например 3000, тк он у нас по дефолту Next.

Nginx

Для простоты мы будем править напрямую основной конфигурационный файл /etc/nginx/nginx.conf, как Вы понимаете на рабочем проекте так делать не надо — разберитесь с  папками /etc/nginx/sites-available/ и /etc/nginx/sites-enabled.

nano /etc/nginx/nginx.conf

Как установить Nginx , подробно описано на официальном сайте, все зависит от Вашей операционной системы очевидно.

Итак, наши настройки для сервера (выжимка), естественно *_INSERT_IP_ADRESS_* надо заменить на Ваш ip сервера и our_best_site на Ваш домен и всю структуру папок проверить (/home/our_best_site/public_html и тд):

server {
                server_name our_best_site.ru www.our_best_site.ru;
                listen *_INSERT_IP_ADRESS_*;
                root /home/our_best_site/public_html;
                index index.php index.htm index.html;
                access_log /var/log/virtualmin/our_best_site.ru_access_log;
                error_log /var/log/virtualmin/our_best_site.ru_error_log;
                fastcgi_param GATEWAY_INTERFACE CGI/1.1;
                fastcgi_param SERVER_SOFTWARE nginx;
                fastcgi_param QUERY_STRING $query_string;
                fastcgi_param REQUEST_METHOD $request_method;
                fastcgi_param CONTENT_TYPE $content_type;
                fastcgi_param CONTENT_LENGTH $content_length;
                fastcgi_param SCRIPT_FILENAME /home/our_best_site/public_html$fastcgi_script_name;
                fastcgi_param SCRIPT_NAME $fastcgi_script_name;
                fastcgi_param REQUEST_URI $request_uri;
                fastcgi_param DOCUMENT_URI $document_uri;
                fastcgi_param DOCUMENT_ROOT /home/our_best_site/public_html;
                fastcgi_param SERVER_PROTOCOL $server_protocol;
                fastcgi_param REMOTE_ADDR $remote_addr;
                fastcgi_param REMOTE_PORT $remote_port;
                fastcgi_param SERVER_ADDR $server_addr;
                fastcgi_param SERVER_PORT $server_port;
                fastcgi_param SERVER_NAME $server_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_param HTTPS $https;

                location / {
                        proxy_pass http://localhost:3000/;
                }

                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                listen *_INSERT_IP_ADRESS_*:443 ssl;
                ssl_certificate /home/our_best_site/ssl.combined;
                ssl_certificate_key /home/our_best_site/ssl.key;
        }

У Nginx куча настроек и улучшать можно постоянно, но основная магия в паре строк, те мы проксируем все запросы на «/» на наш node сервер, который мы скоро запустим:

location / {
proxy_pass http://localhost:3000/;
}

Для работы SSL, нам надо получить сертификаты в сертификационном центре и указать пути к этим файлам:

ssl_certificate /home/our_best_site/ssl.combined;
ssl_certificate_key /home/our_best_site/ssl.key;

Запускаем приложение

Какие файлы нам нужны от Next.js для запуска?

Для начала нам нужно запустить в терминале компиляцию проекта npm run build, в итоге мы увидим что-то похожее. Next создаст все необходимые файлы, статические и для рендеринга на сервере.

Осталось понять, что же нам нужно перенести на рабочий сервер в простейшем варианте, без Git и прочих полезных вещей.

Мы идем на сервер, создаем рабочую папку для Next и копируем туда файлы и папки:

  1. /.next — основная рабочая папка;
  2. /public — папка со статическими публичными файлами, например favicon.ico и robots.txt;
  3. next.config.js — конфигурационный файл next, куда надо не забыть включить домены для картинок и например webpack5: true;
  4. package.json — конфигурационный файл приложения.

Далее осталось запустить в этой папке npm install, при этом менеджер проанализирует package.json и автоматически сгенерирует папку /node_modules, со всеми необходимыми пакетами. Ее не надо копировать из среды разработки.

Все, теперь достаточно запустить npm run start или любой нужный скрипт из package.json и, если Вы правильно указали порт, а у нас Nginx проксирует на 3000, все заработает. Но, это неудобно, тк стоит закрыть терминал — все умрет. Эту проблемы нам поможет решить отличный менеджер процессов PM2.

Запускаем Nextjs через PM2 (менеджер процессов)

Подробно прочитать про этот менеджер процессов можно в мануале на официальном сайте, мы же укажем только необходимый минимум

Итак, устанавливаем pm2 командой (возможно Вам потребуется использовать sudo):

npm install pm2 -g

Запуск процессов

Для запуска проекта в простом варианте можно использовать что-то вроде, при этом не забудьте перейти в рабочую папку проекта nextjs.

pm2 start npm -- start

А так же полезные ключи:

# Указываем имя запущенного приложения
--name <app_name>

# Устанавливаем наблюдение за файлами проекта и перезапускаем приложение при их изменении
--watch

# Устанавливаем лимит памяти до перезагрузки приложения
--max-memory-restart <200MB>

# Определяем путь к файлу логов
--log <log_path>

# Прокидываем аргументы в скрипт
-- arg1 arg2 arg3

# Задержка между автоматическими перезапусками
--restart-delay <delay in ms>

# Добавлять префикс времени в логах
--time

# Не перезапускать автоматически приложение
--no-autorestart

# Определяем задачу крон для принудительного перезапуска (forced restart)
--cron <cron_pattern>

Управление и мониторинг процессов

Для управления запущенными процессами можно использовать команды:

$ pm2 restart app_name
$ pm2 reload app_name
$ pm2 stop app_name
$ pm2 delete app_name

Вместо app_name можно использовать:

  • all для управления всеми процессами;
  • id для управления процессом по его id.

Мониторить запущенные процессы можно парой удобных команд:

// онлайн мониторинг в экране терминала
$ pm2 monit

// список процессов
# pm2 list

Пример вывода для pm2 monit:

Команда pm2 monit

Итого по pm2

Теперь мы можем запустить наш проект, со всеми ключами. Представим, что наше приложение лежит в папке /home/our_best_site/public_html/nextjs:

$ cd /home/our_best_site/public_html/nextjs
$ pm2 start npm --watch --ignore-watch="node_modules" --restart-delay=10000 --name "app_name1" -- start

Из строки видно, что запускаем мы в рабочей папке наш процесс npm start с именем app_name1, при этом следим за изменениями с задержкой перезапуска 10000мс и игнорируем папку node_modules.

При этом в терминале мы увидим наше приложение:

Команда pm2 start npm --name "app_name1" -- start

Заключение

В результате мы получаем nextjs приложение, которое работает на 3000 порту и все запросы (80 и 443 портов) в него проксируются через nginx. Управление приложением происходит через менеджер pm2. Стоит отметить, что все написанное будет работать и для React.js приложения с минимальными правками.

Ура, все работает)