🟢
Хостинг

Деплой Nuxt на сервер: SSR, статическая генерация, PM2 и Nginx

06.11.2026
← Все статьи

Nuxt — фреймворк на основе Vue, который из одного и того же кода позволяет собрать и динамический сайт с рендерингом на сервере, и полностью статический сайт. Этот выбор нужно сделать до деплоя, потому что от него зависит, какой сервер понадобится. Если страницы при каждом запросе берут свежие данные из базы, пользователи входят в аккаунт или нужен серверный API, нужен VPS с Node.js. Если сайт в основном состоит из неизменных страниц, его можно сгенерировать в статический HTML и разместить даже на обычном хостинге.

Результат сборки Nuxt: папка .output

Nuxt 3 и новее используют серверный движок Nitro. После команды npm run build в корне проекта появляется папка .output. В ней есть часть server и часть public с файлами для браузера. Папка самодостаточна: для запуска на сервере не нужны исходники проекта и полный node_modules, потому что Nitro собирает нужные зависимости внутрь.

npm ci
npm run build
node .output/server/index.mjs

По умолчанию сервер стартует на порту 3000. Порт и адрес меняются переменными окружения PORT и HOST или NITRO_PORT и NITRO_HOST. За Nginx безопаснее слушать только адрес 127.0.0.1.

Деплой на VPS в режиме SSR

На сервере должна быть установлена LTS-версия Node.js. Получаем код через Git и собираем проект. На маленьком сервере сборка может упасть из-за нехватки памяти; в этом случае добавьте swap или соберите проект на своём компьютере и отправьте на сервер только папку .output. Во втором случае операционная система и архитектура сборочной машины и сервера должны совпадать.

cd /var/www
git clone https://github.com/misol/misol-nuxt.git
cd misol-nuxt
npm ci
npm run build

Постоянная работа через PM2

Чтобы приложение не останавливалось при закрытии терминала и само запускалось после перезагрузки сервера, используем PM2. В документации Nuxt тоже приведён пример ecosystem-файла для PM2. В варианте ниже включён cluster-режим: PM2 запустит несколько копий по числу ядер сервера.

// ecosystem.config.cjs
module.exports = {
  apps: [{
    name: "misol-nuxt",
    port: "3000",
    exec_mode: "cluster",
    instances: "max",
    script: "./.output/server/index.mjs",
    env: {
      HOST: "127.0.0.1",
      NUXT_PUBLIC_API_BASE: "https://api.example.uz"
    }
  }]
};
npm install -g pm2
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup

В cluster-режиме не храните сессии и кеш в памяти процесса, иначе в каждой копии они будут разными. Если приложение к этому не готово, установите instances в 1.

Runtime config: настройка без пересборки

Раздел runtimeConfig в nuxt.config.ts можно переопределять переменными окружения во время работы. Для этого имя переменной должно начинаться с NUXT_, а для значений, доступных в браузере, используется NUXT_PUBLIC_. Это очень удобно: при смене адреса API или секретного ключа не нужно пересобирать весь проект, достаточно перезапустить PM2 с новым окружением.

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    apiSecret: "",
    public: {
      apiBase: ""
    }
  }
});
NUXT_API_SECRET=... NUXT_PUBLIC_API_BASE=https://api.example.uz node .output/server/index.mjs

Никогда не кладите секреты в public: всё, что там лежит, попадает в код страницы и в браузер.

Nginx перед приложением

Приложение работает на внутреннем порту, а внешние запросы принимает Nginx. Он подключает SSL-сертификат, включает сжатие и передаёт запросы в Nuxt. Сертификат можно бесплатно получить у Let's Encrypt через Certbot.

server {
    listen 80;
    server_name example.uz;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        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 nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d example.uz

Статическая генерация: хостинг без Node.js

Если сайту не нужна серверная обработка каждого запроса, команда nuxi generate заранее превратит все страницы в HTML-файлы. Результат записывается в .output/public, и его можно загрузить как обычные файлы на любой веб-сервер, в том числе на хостинг с панелью ISPmanager. Такому сайту не нужен процесс Node.js, поэтому он потребляет мало ресурсов и открывается очень быстро.

npx nuxi generate
ls .output/public

Обычно nuxi generate создаёт отдельную папку для каждого маршрута, но динамические страницы, о которых сборка заранее не знает, не генерируются, и при прямом переходе на них можно получить 404. Такие страницы добавьте в список через nitro.prerender.routes.

Практический пример: гостиница в Бухаре

Небольшая гостиница в Бухаре заказала сайт misol.uz на Nuxt. Описания номеров, галерея и страница контактов меняются редко, поэтому на первом этапе сайт сгенерировали через nuxi generate и разместили на обычном хостинге. Позже, когда понадобились онлайн-бронирование и показ занятости номеров в реальном времени, проект перенесли на VPS в режиме SSR, а PM2 и Nginx настроили по описанной схеме. Сам код почти не изменился — поменялись только команда сборки и способ размещения.

Если не знаете, что выбрать, начните с простого: для статического сайта хватит хостинга sayt.uz, а когда появятся динамические функции, можно перейти на VPS.

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

🐘 Что нового в PHP 8.4: property hooks, асимметричная видимость и другое 🔀 nvm: управление версиями Node.js, переключение и .nvmrc 📧 Как создать почтовый ящик в ISPmanager и настроить его 🚀 Деплой без простоя: папки релизов и переключение через symlink
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский ✓ 🇬🇧 English