Kompyuter qanday ishlaydi
15-bob

Botni serverga joylash

Bot noutbukda ishlayapti, lekin qopqoqni yopsangiz u ham uxlaydi. Bu bobda kodni doimiy yoqiq turadigan serverga ko'chiramiz: SSH, systemd, Docker, Nginx va HTTPS.

Bu bob asl darslikka qo'shimcha sifatida onlayn nashr uchun yozilgan.

Oldingi boblarda kompyuter ichida nima bo'lishini o'rgandik. Endi amaliy savol: yozgan botingiz qayerda ishlashi kerak? Uni node bot.js bilan noutbukda ishga tushirish oson, lekin bu vaqtinchalik yechim. Bu bobda botni haqiqiy serverga joylash yo'lini boshidan oxirigacha ko'ramiz.

push pull ssh · port 22 Noutbuk (siz) $ _ qopqoq ochiq · ishlayapti IP 84.54.71.9 — o'zgaruvchan NAT ortida · tashqaridan yopiq GitHub repo: botmain: 9f8e7d kod saqlanadi, ishlamaydi clone / pull manbai VPS · 185.199.108.153 · Ubuntu 24.04 sshd · :22muhammad@vps ~/bot $ _ systemd · PID 1bot.service: enabledRestart=always · RestartSec=5yuklanishda ham ko'taradi node bot.js · PID —tinglaydi: 127.0.0.1:3000webhook: —.env → BOT_TOKEN Nginx · :443 · TLS→ 127.0.0.1:3000 ufw22443qolgani yopiq · 24/7 · doimiy IP uptime: 41 kun · yuk 0.02 · 2 vCPU · 2 GB data-markaz: ikki tomonlama elektr, sovutish, 10 Gbit/s Nega noutbuk emas? qopqoq yopildi → uxlaydi, jarayon to'xtaydi uy IP si vaqti-vaqti bilan o'zgaradi NAT ortida: tashqaridan ulanib bo'lmaydi server: 24/7 ✓ doimiy IP ✓ 443 ochiq ✓
git pushgit pullsystemdIshlayaptiQopqoq yopildiXulosa
Pastga suring: kod noutbukdan serverga boradi.
Noutbukdan serverga. Kod git orqali serverga boradi, u yerda nazoratchi (systemd yoki PM2) botni to'xtovsiz ushlab turadi.

15.1. Server qayerda turadi

1.3-bo'limda aytganimizdek, server — doimiy yoqiq turadigan oddiy kompyuter. Bunday kompyuterlar data-markazlarda turadi: minglab server javonlarga terilgan, ularga ikki tomonlama elektr, sovutish va tezkor internet ulangan bino. Butun bir serverni ijaraga olish mumkin (alohida server, dedicated) — bu qimmat. Ko'pincha VPS olinadi: bitta kuchli server virtual mashinalarga bo'linadi va har biriga alohida foydalanuvchi joylashtiriladi. Odatiy VPS — 1–2 yadro, 1–2 GB RAM, 20–40 GB SSD — Telegram bot uchun bemalol yetadi va oyiga bir necha dollar turadi. Uchinchi yo'l — "serverless": siz faqat funksiya yozasiz, uni qachon va qaysi mashinada ishga tushirishni provayder hal qiladi; kam so'rovda arzon, lekin nazorat kam.

Nega noutbukdan ishlatib bo'lmaydi? Uchta sabab. Birinchi, noutbuk uxlaydi: qopqoq yopildi — jarayon to'xtadi. Ikkinchi, uy internetining IP manzili vaqti-vaqti bilan o'zgaradi, Telegram esa webhook uchun doimiy manzil kutadi. Uchinchi, uy routeri NAT ortida: butun uy bitta tashqi IP bilan chiqadi va tashqaridan sizning kompyuteringizga ulanib bo'lmaydi. 13.4-bo'limdagi mijoz-server modeli esa doimiy ochiq IP va 24 soat kutib turadigan dasturni talab qiladi.

15.2. SSH va Linux terminali

Serverga ekran va klaviatura ulanmagan. Unga tarmoq orqali SSH bilan kiriladi: ssh muhammad@185.199.108.153. SSH — shifrlangan terminal: siz yozgan har bir buyruq va uning natijasi 13.3-bo'limdagi kabi shifrlangan tunnel orqali o'tadi. Parol o'rniga kalit juftligi ishlatish xavfsizroq: yopiq kalit sizning kompyuteringizda qoladi, ochiq kalit esa serverdagi ~/.ssh/authorized_keys fayliga yoziladi. Kirishda server tasodifiy son yuboradi, siz uni yopiq kalit bilan imzolaysiz, server imzoni ochiq kalit bilan tekshiradi — maxfiy narsa tarmoqdan umuman o'tmaydi.

TCP :22 · qo'l berish shifrlangan tunnel (chacha20-poly1305) — Terminal (noutbuk) $ _ ~/.ssh/id_ed25519 — yopiq kalitfaqat shu kompyuterda · ruxsat 600 ~/.ssh/known_hostsserver kaliti: hali noma'lum Server · 185.199.108.153 sshd · :22 · PID 812ulanish kutmoqda host kaliti · ssh_host_ed25519_keySHA256:Ab3k…9Qz — serverning pasporti ~/.ssh/authorized_keysssh-ed25519 AAAAC3… muhammad@laptop /var/log/auth.log:
ssh muhammad@185.199.108.153 · port 22
TCPHost kalitiKalitChaqiriqImzoTekshiruvShell
Pastga suring yoki "Ulan" ni bosing.
SSH orqali kirish. Ochiq va yopiq kalit juftligi: server sizni parolsiz, imzo orqali taniydi.

Kirganingizdan keyin bir necha buyruq yetadi: ls (fayllar ro'yxati), cd (papkaga o'tish), nano bot.js (oddiy muharrir), htop (jarayonlar, CPU va RAM jonli), df -h (disk qancha to'lgan), free -m (megabaytlarda bo'sh xotira). root hamma narsani qila oladi, shuning uchun kundalik ish oddiy foydalanuvchidan qilinadi, kerak bo'lganda sudo bilan bitta buyruqqa vaqtincha to'liq huquq olinadi. Firewall faqat kerakli portlarni ochadi, qolgani yopiq:

sudo ufw allow OpenSSH    # 22-port; buni unutsangiz, o'zingiz ham kirolmaysiz
sudo ufw allow 443/tcp    # HTTPS — Telegram webhook shu portga keladi
sudo ufw enable

PostgreSQL'ning 5432-porti ochilmaydi: baza faqat shu serverning ichidan, localhost orqali so'rov oladi.

15.3. Dastur doimiy ishlashi kerak

SSH orqali node bot.js deb yozsangiz, bot ishlaydi — terminalni yopguningizcha. 11.3-bo'limdagi jarayon o'zini ishga tushirgan terminalga bog'langan: terminal yopilganda OS unga SIGHUP signalini yuboradi va jarayon tugaydi. Serverda dastur nazoratchi ostida ishlashi kerak. Linux'da bu systemd — yuklanishda birinchi bo'lib ishga tushadigan jarayon (11.1). Unga kichik "unit" fayl yoziladi:

# /etc/systemd/system/bot.service
[Unit]
Description=Telegram bot
After=network-online.target

[Service]
User=muhammad
WorkingDirectory=/home/muhammad/bot
EnvironmentFile=/home/muhammad/bot/.env
ExecStart=/usr/bin/node bot.js
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

# sudo systemctl enable --now bot      # hozir ham, qayta yuklanganda ham
# journalctl -u bot -f                 # loglarni jonli ko'rish
Terminaldan: node bot.js SSH sessiya · pts/0ochiq bash · PID 4100sessiya rahbari (ota) node bot.js · PID 4123ishlayapti · javob beradi terminalni yopish = jarayonni o'ldirish Nazoratchi ostida: systemd systemd · PID 1bot.service · Restart=always RestartSec=5 taymer— node bot.js · PID 4180ishlayapti · javob beradi qulasa ham, server qayta yuklansa ham — qayta ko'tariladi
IshlayaptiSIGHUPO'ldiQulashTaymerQayta tirildiXulosa
Pastga suring: ikki jarayonning taqdiri.
Jarayonning hayoti. Terminalga bog'langan jarayon terminal bilan birga o'ladi; nazoratchi ostidagi jarayon qulasa ham qayta tiriladi.

Restart=always degani: bot xato bilan tugasa, systemd uni 5 soniyadan keyin qayta ishga tushiradi; server qayta yuklansa ham bot avtomatik ko'tariladi. Loglar journalctl -u bot -f bilan o'qiladi. Node.js olamida shu ishni PM2 ham qiladi:

npm install -g pm2
pm2 start bot.js --name bot     # ishga tushirish va kuzatish
pm2 logs bot                    # loglar
pm2 startup && pm2 save         # server qayta yuklanganda ham ko'tarilsin

Tokenni kodga yozmang: bot.js GitHub'ga tushadi va tokenni bir soat ichida birov topadi. Token muhit o'zgaruvchisida saqlanadi: serverda .env fayl (BOT_TOKEN=123456:ABC...) yaratiladi, systemd uni EnvironmentFile orqali o'qiydi, kodda esa process.env.BOT_TOKEN yoziladi. .env .gitignore'ga kiritiladi.

15.4. Docker: "menda ishlaydi" muammosi

Klassik muammo: "menda ishlaydi, serverda ishlamaydi". Noutbukda Node 22, serverda 18; bir kutubxonaning versiyasi boshqa. Docker bu muammoni dastur bilan birga uning butun muhitini "qadoqlash" orqali hal qiladi. Image — bu qolip: fayl tizimining muzlatilgan nusxasi, u qatlamlarga bo'lingan. Asosda kichik Linux (Alpine, atigi 5 MB), ustida Node.js, ustida npm paketlar, eng tepada sizning kod. 12-rasmdagi abstraksiya qatlamlari kabi har qatlam pastdagisiga tayanadi; kodni o'zgartirsangiz, faqat eng yuqori qatlam qayta quriladi. Container — shu qolipdan ishga tushirilgan jarayon; bitta image'dan istalgancha konteyner ochish mumkin. Image Dockerfile bilan tasvirlanadi:

FROM node:22-alpine              # asos qatlam: Alpine Linux + Node.js 22
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev            # paketlar qatlami (package.json o'zgarmasa keshdan)
COPY . .                         # sizning kod — eng yuqori qatlam
ENV NODE_ENV=production
CMD ["node", "bot.js"]
Image bot:1.0 · docker build faqat o'qish (read-only) · diskda · qatlam = diff o'zgarmagan qatlam keshdan olinadi docker run → konteynerlar bot-1 · —yozish qatlami (writable) · 2 MBpid ns: o'zining "1"-jarayoni bot-2 · —o'z yozish qatlami · o'z tarmoq nsbir xil image, alohida jarayon image = fayllar (disk) container = jarayon (RAM, CPU) Bitta Linux yadrosi (serverniki) namespaces: pid · net · mnt · utshar konteyner o'zini yolg'iz deb biladi cgroups: CPU 1.0 · RAM 512 MB bot-1: CPU 0% · RAM 0 MB Apparat: 2 vCPU · 2 GB · 40 GB SSDyadro 6.8.0 · docker 27 · overlay2 Virtual mashinayuklanish: — s ilova A ilova B Mehmon OS + o'z yadrosi · 1.2 GB Mehmon OS + o'z yadrosi · 1.2 GB Hypervisor (KVM) — apparatni taqlid qiladi Apparat: CPU, RAM, disk Konteyneryuklanish: — s bot · 12 MB postgres · 80 MB nginx · 8 MB Docker: izolyatsiya — namespace + cgroup Bitta Linux yadrosi (serverniki) — umumiy Apparat: CPU, RAM, disk
BuildRunStopVMKonteynerXulosa
Pastga suring: image quriladi, konteynerlar ishga tushadi.
Image, konteyner va virtual mashina. Image — o'zgarmas qatlamlar, konteyner — undan ishga tushgan jarayon; konteynerlar serverning yadrosini bo'lishadi, VM esa o'z yadrosini yuklaydi.

Konteyner virtual mashina emas. VM o'z yadrosi bilan butun OS'ni yuklaydi — bu gigabaytlar va daqiqalar. Konteyner esa serverning Linux yadrosidan foydalanadi, faqat fayllar, jarayonlar va tarmoq izolyatsiya qilingan — megabaytlar va soniyalar. Bot va baza birga docker compose bilan tasvirlanadi: compose.yaml faylida ikkita xizmat — bot (o'z Dockerfile'idan quriladi) va postgres (tayyor image); docker compose up -d bilan ikkisi ham ko'tariladi, bazaning fayllari esa volume'da saqlanadi — konteyner o'chsa ham ma'lumot qoladi.

15.5. Domen, Nginx va HTTPS

Telegram webhook'i faqat HTTPS manzilga yuboriladi. Sababi 13.3-bo'limda: Telegram sizning serveringiz haqiqiy ekanini sertifikat orqali tekshiradi, yo'ldagi routerlar esa foydalanuvchi xabarlarini o'qiy olmaydi. Sertifikat IP'ga emas, domenga beriladi. Shuning uchun avval domen olinadi va DNS'da A-yozuv (13.2) serveringiz IP'siga yo'naltiriladi: bot.misol.uz → 185.199.108.153.

Node.js dasturi to'g'ridan-to'g'ri 443-portni tinglashi shart emas. Oldida Nginx turadi — reverse proxy: u 443-portda TLS'ni yechadi va so'rovni oddiy HTTP sifatida localhost:3000 ga uzatadi. Sertifikat bir joyda turadi, Node.js esa root huquqisiz, oddiy portda ishlaydi.

# /etc/nginx/sites-available/bot
server {
    listen 443 ssl;
    server_name bot.misol.uz;
    ssl_certificate     /etc/letsencrypt/live/bot.misol.uz/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/bot.misol.uz/privkey.pem;

    location /webhook {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
    }
}

Sertifikat Let's Encrypt'dan bepul olinadi: sudo certbot --nginx -d bot.misol.uz. Certbot domen sizniki ekanini tekshiradi, sertifikatni Nginx sozlamasiga o'zi qo'shadi va har 90 kunda yangilab turadi. Oxirgi qadam — Telegram'ga botning manzilini aytish:

curl -F "url=https://bot.misol.uz/webhook" \
     https://api.telegram.org/bot<TOKEN>/setWebhook
HTTPS Telegram serverlari 149.154.167.220 Bot API · webhookbot.misol.uz → ? DNS · :53 A-yozuv (siz sozlagan)→ 185.199.108.153 VPS 185.199.108.153 · ufw: faqat 22 va 443 ufw 22 ssh 80 443 3000 5432 yashil: ochiq qizil: yopiq ichkari ✓ Nginx · :443 · TLS shu yerda yechiladisertifikat: bot.misol.uz (Let's Encrypt)location /webhook → 127.0.0.1:3000 Node bot · 127.0.0.1:3000 · PID 4180POST /webhook → JSON o'qiladikutmoqda PostgreSQL · 127.0.0.1:5432SELECT name FROM users WHERE tg_id=4471— t = 0 ms tashqaridan 3000 va 5432 ga hech kim kira olmaydi
DNSHTTPS :443NginxNode :3000SQL :5432JavobXulosa
Pastga suring: bitta webhook so'rovining serverdagi yo'li.
Bitta xabarning serverdagi yo'li. DNS nomni IP'ga aylantiradi, Nginx 443-portda TLS'ni yechadi, bot 3000-portda ishlaydi, baza esa faqat ichkaridan ochiq.

Shundan keyin har bir xabar 30-rasmdagi yo'l bilan serveringizga POST so'rov sifatida keladi. Nimadir ishlamasa, getWebhookInfo Telegram ko'rgan oxirgi xatoni ko'rsatadi.

15.6. Kuzatuv va xatolarni topish

Server ishga tushdi — endi uni kuzatish kerak. Uchta resurs muhim. CPU: htop'da 100% uzoq tursa, qayerdadir cheksiz sikl bor; bitta oqimli Node.js'da bu butun botni to'xtatadi. RAM: botning xotirasi kundan-kunga o'sib borsa, bu xotira oqishi (12.3): obyektlarga havola qolgani uchun axlat yig'uvchi ularni bo'shata olmaydi; 1 GB to'lganda OS jarayonni o'ldiradi (OOM), nazoratchi uni qayta ko'taradi va sikl takrorlanadi. Disk: eng ko'p uchraydigan halokat — loglar diskni to'ldiradi va bot bazaga ham, logga ham yoza olmaydi (ENOSPC xatosi). Log aylantirish (logrotate, pm2-logrotate) eski fayllarni siqib, ma'lum hajmdan keyin o'chirib turadi.

CPUhtop 0 % RAMfree -m · 1 GB 0 % Diskdf -h · 20 GB 0 % 80% — ogohlantirish chegarasi kun 1 bot.serviceactive (running)PID 4180 · 96 MB OOM killer: tinch journalctl -f
KuzatuvRAM oqishiOOMDisk to'lmoqdaENOSPClogrotateXulosa
Pastga suring: 30 kunlik kuzatuv 15 soniyada.
Uch ko'rsatkich. CPU tebranadi, oqayotgan RAM to'lguncha o'sadi, disk esa loglardan asta-sekin to'ladi — va to'lgan kuni bot yozolmay qoladi.

Bot javob bermay qolganda oddiy tekshiruv ro'yxati yordam beradi:

  1. systemctl status bot yoki pm2 status — jarayon umuman ishlayaptimi?
  2. journalctl -u bot -n 50 yoki pm2 logs bot — oxirgi 50 qator nima deyapti?
  3. df -h va free -m — disk yoki xotira to'lib qolmadimi?
  4. curl https://bot.misol.uz/health — Nginx va sertifikat tirikmi?
  5. getWebhookInfo — Telegram nima deb shikoyat qilyapti?

Healthcheck — botdagi kichik /health manzili, u shunchaki 200 OK qaytaradi. Tashqi kuzatuv xizmati uni har daqiqa so'rab turadi va javob kelmasa sizga xabar yuboradi. Va nihoyat, zaxira nusxa: pg_dump har kuni bazani faylga saqlaydi, fayl boshqa serverga ko'chiriladi. Server bir soatda qayta quriladi; foydalanuvchilar bazasi esa qaytmaydi.

Asosiy g'oya: botni serverga joylash — kitobdagi barcha qatlamlarni amalda qo'llash. OS jarayonlarni boshqaradi (systemd), tarmoq paketlarni yetkazadi (DNS, 443-port), shifrlash ishonchni beradi (TLS, SSH), xotira va disk esa chegaralangan. Server sehrli emas: doimiy yoqiq, doimiy IP'li, nazorat ostidagi oddiy kompyuter.
Amaliy xulosa: minimal ishonchli sxema shunday: VPS + SSH kalit + ufw (22, 443) + systemd yoki PM2 + .env'dagi token + Nginx + certbot + setWebhook + kunlik pg_dump. Docker shart emas, lekin "menda ishlaydi" muammosi boshlansa, yechim aynan u. Har o'zgarishdan keyin journalctl -u bot -f ni ochib qo'ying.
Tekshirish: bob oxiridagi test