Запуск на сервере
На сервере проект запускают не так, как при разработке. Режим start:dev следит за файлами и компилирует TypeScript на лету — это медленно и не нужно. Вместо этого код один раз собирают в JavaScript и запускают обычным Node.js.
Сборка
npm ci
npm run buildnpm ci ставит пакеты строго по package-lock.json. npm run build компилирует папку src в dist. Главный файл после сборки — dist/main.js.
Запуск
NODE_ENV=production npm run start:prodСкрипт start:prod выполняет node dist/main. В терминале появится строка Nest application successfully started, и API начнёт отвечать на порту из переменной PORT.
Переменные окружения
На сервере значения задают не в коде, а в окружении — в настройках хостинга, в файле сервиса systemd или в .env, созданном прямо на сервере:
NODE_ENV=production
PORT=3000
DB_PATH=/var/data/blog.sqlite
JWT_SECRET=длинная-случайная-строка-только-для-сервераДлинный случайный секрет можно получить командой node -e "console.log(require('crypto').randomBytes(32).toString('hex'))".
Настройки для рабочего режима
// src/app.module.ts
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
type: 'better-sqlite3',
database: config.getOrThrow<string>('DB_PATH'),
autoLoadEntities: true,
synchronize: config.get('NODE_ENV') !== 'production',
}),
}),На сервере synchronize выключен: таблицы меняют миграциями TypeORM, а не автоматически. Для большой нагрузки SQLite обычно заменяют на PostgreSQL — меняются только type и параметры подключения.
// src/main.ts
const app = await NestFactory.create(AppModule);
app.enableCors({ origin: 'https://example.com' });
app.enableShutdownHooks();enableCors() разрешает запросы к API со страниц сайта example.com. enableShutdownHooks() даёт приложению корректно закрыть соединение с базой, когда сервер останавливает процесс.
Чтобы процесс не останавливался
Если просто запустить node dist/main и закрыть терминал, сервер остановится. Процесс держат запущенным менеджером процессов — например, PM2:
npm i -g pm2
pm2 start dist/main.js --name blog-api
pm2 savePM2 перезапустит приложение после сбоя, а pm2 logs blog-api покажет журнал. Другие варианты — сервис systemd или контейнер Docker.
Порядок выкладки
| Шаг | Команда |
|---|---|
| Получить код | git pull |
| Поставить пакеты | npm ci |
| Собрать | npm run build |
| Применить миграции | npx typeorm migration:run -d dist/data-source.js |
| Перезапустить | pm2 restart blog-api |
Шаг с миграциями нужен, если вы их используете; файл data-source описывает подключение для консольной утилиты TypeORM.
Частая ошибка
Код собрали, но на сервере не задали переменные окружения. Приложение падает при запуске, или, что хуже, запускается со значениями по умолчанию: другой базой и пустым секретом. Используйте getOrThrow() для обязательных настроек — тогда сервер не запустится, пока все нужные переменные не заданы, и ошибка сразу назовёт недостающую.