🚀
Хостинг

Деплой Next.js на свой сервер: build, PM2, Nginx и SSL

14.11.2026
← Все статьи

Когда речь заходит о деплое Next.js, многие первым делом вспоминают облачные платформы. Они удобны, но по мере роста проекта всё важнее становятся стоимость, место хранения данных и контроль над сервером. Для сайта, рассчитанного на пользователей в Узбекистане, локальный VPS к тому же может ускорить загрузку страниц. На своём сервере Next.js работает через next start как обычное Node.js-приложение, поэтому его можно развернуть на любом Linux-сервере.

Подготовка сервера

Начнём с чистого сервера на Ubuntu или Debian. Сначала обновим систему и создадим отдельного пользователя для приложения, потому что запускать его от root небезопасно. Затем установим LTS-версию Node.js. Каждая версия Next.js требует минимальную версию Node.js — сверьтесь с документацией той версии, что используется в проекте.

sudo apt update && sudo apt upgrade -y
sudo adduser deploy
sudo usermod -aG sudo deploy
su - deploy
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install --lts
node -v

Установка через nvm позволяет держать на сервере несколько версий Node.js. Если проект один, можно поставить Node.js и пакетным менеджером системы — главное, чтобы версия подходила под требования.

Загрузка проекта и сборка

Удобнее всего доставлять код на сервер через Git. Репозиторий клонируется, зависимости устанавливаются, и собирается production-сборка. Сборка заметно нагружает сервер: на маленьком VPS при нехватке памяти процесс падает с ошибкой «JavaScript heap out of memory». В этом случае добавьте swap или собирайте проект на другой машине.

cd /var/www
sudo mkdir misol-next && sudo chown deploy:deploy misol-next
git clone https://github.com/misol/misol-next.git misol-next
cd misol-next
npm ci
cp .env.example .env.production
nano .env.production
npm run build

npm ci ставит точные версии из package-lock.json, поэтому приложение на сервере совпадает с вашим локальным. Не забудьте про переменные окружения: значения с префиксом NEXT_PUBLIC_ встраиваются в код во время сборки, и после их изменения пересборка обязательна.

Запуск через PM2

Готовую сборку нужно запустить так, чтобы она не зависела от терминала. Менеджер процессов PM2 держит приложение в фоне, поднимает его после падения и запускает при загрузке сервера. По умолчанию Next.js слушает порт 3000; оставим его доступным только изнутри, а наружу выпустим через Nginx.

npm install -g pm2
pm2 start npm --name misol-next -- start -- -p 3000 -H 127.0.0.1
pm2 save
pm2 startup

Параметр -H 127.0.0.1 заставляет приложение слушать только локальный адрес, и никто не сможет подключиться к порту 3000 напрямую в обход Nginx. Не забудьте скопировать и выполнить команду sudo, которую выводит pm2 startup.

Nginx как reverse proxy

Nginx принимает внешние запросы, кеширует статику и обслуживает SSL, а Next.js отвечает только за динамическую часть. Конфигурация ниже написана для домена example.uz.

sudo apt install nginx -y
sudo nano /etc/nginx/sites-available/misol-next
server {
    listen 80;
    server_name example.uz www.example.uz;

    location /_next/static/ {
        proxy_pass http://127.0.0.1:3000;
        expires 365d;
        add_header Cache-Control "public, immutable";
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
sudo ln -s /etc/nginx/sites-available/misol-next /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Файлы в /_next/static/ содержат хеш в имени и меняются при каждой сборке, поэтому кешировать их надолго безопасно. nginx -t предупредит об ошибке в конфигурации ещё до перезагрузки.

Домен и бесплатный SSL

Чтобы домен вёл на сервер, A-запись в DNS должна указывать на IP-адрес VPS. Это делается в разделе DNS домена в кабинете sayt.uz. Когда запись разойдётся, получаем сертификат Let's Encrypt через Certbot. Certbot сам обновит конфигурацию Nginx и установит таймер автоматического продления.

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.uz -d www.example.uz
sudo certbot renew --dry-run

Выкладка новой версии

При каждом изменении кода повторяются одни и те же шаги, поэтому их удобно собрать в небольшой скрипт. Если сборка завершится с ошибкой, скрипт остановится, и продолжит работать старая версия.

#!/bin/bash
set -e
cd /var/www/misol-next
git pull
npm ci
npm run build
pm2 reload misol-next

Учтите: next build перезаписывает существующую папку .next, поэтому работающее приложение во время сборки может выдавать ошибки. В крупных проектах надёжнее собирать в отдельной папке или на CI-сервере и переносить готовый результат.

Практический пример: стоматология в Ташкенте

Стоматологическая клиника в Ташкенте заказала сайт example.uz на Next.js: страницы услуг статические, а форма онлайн-записи работает через API route. Сайт развернули на VPS с 2 ГБ памяти по описанной схеме, а для сборки добавили 2 ГБ swap. Страницы быстро открываются благодаря кешу Nginx, заявки на запись остаются в базе на собственном сервере клиники, а администратор при добавлении новой услуги просто запускает скрипт деплоя.

Если хотите развернуть проект похожим образом, сначала проверьте на своём компьютере, сколько памяти занимает сборка, и выбирайте тариф VPS с учётом этого.

Похожие статьи

💾 Снапшот VPS и резервная копия: в чём разница и что вас спасёт 🔄 Обновление сайта через git pull: простой и надёжный деплой на хостинге 🔀 Отдельная версия PHP для каждого сайта: настройка в ISPmanager 🖥️ Выбор хостинга в Узбекистане в 2026 году: местный или зарубежный сервер
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский ✓ 🇬🇧 English