🚀
Хостинг

NestJS иловасини production'га чиқариш: build, PM2, Nginx ва SSL

11.11.2026
← Барча мақолалар

NestJS локал компьютерда npm run start:dev билан жуда қулай ишлайди: код ўзгарса сервер ўзи қайта ишга тушади, хатолар дарҳол терминалда кўринади. Лекин production муҳити бошқа талаблар қўяди. У ерда илова кечаю кундуз тўхтамасдан ишлаши, сервер қайта юкланганда ўзи кўтарилиши, махфий калитларни коддан алоҳида сақлаши ва ташқи дунё билан фақат ҳимояланган HTTPS орқали гаплашиши керак. Ушбу мақолада Тошкентдаги кичик етказиб бериш хизмати учун ёзилган API мисолида NestJS иловасини VPS серверга босқичма-босқич чиқарамиз.

Қайси сервер керак: VPS ёки оддий хостинг

NestJS доимий ишлаб турадиган Node.js жараёни ҳисобланади, яъни у PHP сайтлар каби ҳар сўровда ишга тушиб, кейин ўчиб қолмайди. Шу сабабли унга ўз портини тинглаб турадиган ва фон жараёнларни ушлаб тура оладиган муҳит керак. Энг ишончли вариант бу VPS: унда Node.js версиясини ўзингиз танлайсиз, PM2 ёки systemd ўрнатасиз ва Nginx'ни хоҳлаганча созлайсиз. Оддий shared хостингда Node.js иловаларини ишлатиш имконияти тариф ва панел созламаларига боғлиқ, шунинг учун лойиҳани бошлашдан олдин буни sayt.uz кабинетидан ёки техник ёрдам орқали аниқлаб олиш фойдали.

Бизнинг мисолимизда api.example.uz манзилида ишлайдиган буюртмалар API'си бор. У PostgreSQL базасидан фойдаланади, курьерларга Telegram орқали хабар юборади ва мобил илова билан JSON орқали гаплашади. Сервер сифатида Ubuntu ўрнатилган VPS олинган, доменнинг A ёзуви эса шу сервернинг IP манзилига йўналтирилган.

Кодни production учун тайёрлаш

Биринчи навбатда main.ts файлини кўриб чиқинг. Илова портни муҳит ўзгарувчисидан олиши, фақат ички интерфейсни тинглаши ва тўхташ сигналларини тўғри қайта ишлаши керак. enableShutdownHooks() чақируви PM2 ёки systemd жараённи тўхтатганда базага уланишларни тоза ёпишга имкон беради. Nginx орқасида ишлаганда мижознинг ҳақиқий IP манзилини кўриш учун Express'нинг trust proxy созламасини ёқиш ҳам муҳим.

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);
  app.set('trust proxy', 1);
  app.enableShutdownHooks();
  const port = Number(process.env.PORT ?? 3000);
  await app.listen(port, '127.0.0.1');
}
bootstrap();

Махфий маълумотлар, масалан база пароли, JWT калити ва Telegram бот токени, ҳеч қачон код ичида ёки Git омборида сақланмаслиги керак. Уларни сервердаги .env файлига ёзиб, @nestjs/config модули орқали ўқиш одатий йўл. Файлга фақат иловани ишлатадиган фойдаланувчи ўқиш ҳуқуқига эга бўлиши учун chmod 600 .env буйруғини бажаринг.

Серверда build қилиш ва ишга тушириш

Production'да TypeScript коди тўғридан-тўғри ишлатилмайди. nest build уни dist папкасидаги оддий JavaScript файлларга компиляция қилади ва сервер айнан шу файлларни ишга туширади. Боғлиқликларни ўрнатишда npm install ўрнига npm ci ишлатган маъқул, чунки у package-lock.json файлидаги аниқ версияларни ўрнатади ва кутилмаган янгиланишлар сабабли илова бузилиб қолмайди.

cd /var/www/api
git pull
npm ci
npm run build
npm prune --omit=dev
NODE_ENV=production node dist/main.js

Охирги буйруқ илова тўғри ишга тушишини текшириш учун керак. Агар терминалда хато чиқмаса ва curl http://127.0.0.1:3000 жавоб қайтарса, кейинги босқичга ўтиш мумкин.

База миграциялари: synchronize'дан воз кечинг

TypeORM'даги synchronize: true созламаси ишлаб чиқишда қулай, аммо production'да у жадвал тузилмасини ўзи ўзгартириб, маълумотларни йўқотишга олиб келиши мумкин. Шунинг учун реал серверда бу созламани ўчириб, ўзгаришларни миграция файллари орқали қўллаш керак. Prisma ишлатадиган лойиҳаларда бунинг учун алоҳида буйруқ бор, у фақат ҳали қўлланмаган миграцияларни бажаради ва янги миграция яратмайди.

# Prisma
npx prisma migrate deploy

# TypeORM (data-source fayli dist ichida bo'lsa)
npx typeorm migration:run -d dist/data-source.js

Миграциядан олдин базанинг захира нусхасини олиш одатга айлансин. Етказиб бериш хизматида буюртмалар жадвали йўқолса, бу фақат техник муаммо эмас, балки мижозлар билан боғлиқ жиддий бизнес йўқотиш ҳамдир.

PM2 билан доимий ишлатиш

Терминал ёпилганда node dist/main.js жараёни ҳам тўхтайди. Уни фон режимида ушлаб туриш, хато билан йиқилганда қайта кўтариш ва сервер қайта юкланганда автоматик ишга тушириш учун PM2 жараён менежеридан фойдаланамиз. Кластер режими эса иловани бир нечта процессор ядросида параллел ишлатиб, юклама кўп бўлганда жавоб тезлигини оширади.

npm install -g pm2
NODE_ENV=production pm2 start dist/main.js --name api -i 2
pm2 save
pm2 startup systemd
pm2 logs api --lines 50

pm2 startup буйруғи экранга битта sudo буйруғини чиқаради, уни нусхалаб бажариш керак, акс ҳолда сервер қайта юкланганда илова кўтарилмайди. Кластер режимида ҳар бир нусха алоҳида хотирага эга бўлишини унутманг: агар илова хотирада сессия ёки кешни сақласа, уни Redis каби умумий омборга кўчириш лозим.

Nginx reverse proxy ва HTTPS

Илова фақат 127.0.0.1:3000 манзилини тинглайди, ташқи сўровларни эса Nginx қабул қилиб, унга узатади. Бу схема SSL'ни, сиқишни, статик файлларни ва сўровлар ҳажми чекловларини Nginx зиммасига юклайди, NestJS эса фақат бизнес мантиқ билан шуғулланади. WebSocket ишлатилса, Upgrade сарлавҳалари албатта узатилиши керак.

server {
    listen 80;
    server_name api.example.uz;
    client_max_body_size 10m;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
    }
}

Конфигурацияни сақлагач, sudo nginx -t билан синтаксисни текширинг ва sudo systemctl reload nginx билан қайта юкланг. Сўнг Certbot ёрдамида Let's Encrypt сертификатини олинг: sudo certbot --nginx -d api.example.uz. Certbot конфигурацияга 443-порт блокини ўзи қўшади ва сертификатни автоматик янгилаш учун таймер ўрнатади.

Ишга туширишдан кейинги текширувлар

API очилгач, бир неча нарсани албатта текшириб чиқинг. Бу рўйхат биринчи ҳафтадаги энг кўп учрайдиган муаммоларнинг олдини олади:

Янгиланишларни чиқариш жараёнини ҳам олдиндан келишиб олинг. Энг содда вариант: git pull, npm ci, npm run build, миграция ва pm2 reload api. Кластер режимида reload буйруғи нусхаларни бирма-бир алмаштиради, шунинг учун фойдаланувчилар янгиланиш пайтида узилишни сезмайди.

Ўхшаш мақолалар

🖥️ Янги VPS: биринчи 30 дақиқада қилинадиган ишлар ⏱️ max_execution_time: узоқ ишлайдиган PHP скриптлар билан тўғри ишлаш 🥟 Bun runtime: Node.js ўрнига ишлатиш мумкинми ва серверда қандай ишга туширилади 📦 Telegram Bot API локал сервер: катта файллар билан ишлаш учун ўз серверингиз
🌐 Тил
🇺🇿 O'zbek 🇺🇿 Ўзбек ✓ 🇷🇺 Русский 🇬🇧 English