VPS'da production deploy: birinchi loyihani serverga chiqarishning amaliy yo'li
Birinchi loyihani serverga chiqarish — ko'p dasturchi uchun eng qo'rqinchli bosqich. Kod yozishni bilasiz, lekin "deploy", "nginx", "systemd" so'zlari boshqa dunyodek tuyuladi. Men bir necha yildan beri maktab tizimlarining serverlarini boshqaraman va shu tajribadan aytaman: production deploy sirli narsa emas — bir marta o'rganib olinadigan aniq ketma-ketlik. Quyida o'sha ketma-ketlikni ortiqcha murakkabliksiz, bosqichma-bosqich ko'rsataman.
Nega VPS, PaaS emas?
Vercel, Railway, Render kabi PaaS'lar juda qulay: git push qilasiz — sayt jonli. Lekin mahalliy sharoitda uchta sabab VPS foydasiga ishlaydi:
- Narx. 4–8 dollarlik VPS'da bir nechta loyiha, baza va cron'lar bemalol yashaydi. PaaS'da har bir servis alohida pul, baza uchun yana alohida — loyihalar ko'paygani sari farq keskinlashadi.
- To'lov realiyasi. Xalqaro kartadan oylik yechib turadigan servislar bilan ishlash O'zbekistonda hamma uchun ham silliq emas. Mahalliy provayderlar so'mda to'lov qabul qiladi, hujjat kerak bo'lsa — shartnoma ham beradi.
- To'liq nazorat. Nimani o'rnatish, qaysi versiya, qanday sozlash — hammasini o'zingiz hal qilasiz. Maktab tizimlari bilan ishlaganda bu men uchun hal qiluvchi omil: ma'lumot qayerda turgani va unga kim kira olishi aniq bo'lishi shart.
Kamchiliklarini ham halol aytish kerak: xavfsizlik, yangilanishlar, monitoring — hammasi sizning bo'ynıngizda. Server tunda yiqilsa, uni siz turg'izasiz. Loyihangiz bitta landing bo'lsa va vaqtingiz qimmat bo'lsa, PaaS haqiqatan yaxshiroq tanlov bo'lishi mumkin. Lekin backend, baza va doimiy trafikli real loyiha uchun VPS'ni o'rganishga arziydi.
Minimal xavfsizlik bazasi
Yangi VPS internetga chiqqan zahoti botlar parol terib "urishni" boshlaydi — bu gipoteza emas, auth loglarini ochsangiz o'zingiz ko'rasiz. Shuning uchun birinchi 15 daqiqada to'rtta ish qilinadi:
# 1. SSH kalitni serverga yuklash (lokal mashinada)
ssh-copy-id deploy@server-ip
# 2. Root login va parol bilan kirishni o'chirish
# /etc/ssh/sshd_config ichida:
# PermitRootLogin no
# PasswordAuthentication no
sudo systemctl restart sshd
# 3. Firewall: faqat kerakli portlar ochiq
sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable
# 4. fail2ban — takroriy noto'g'ri urinishlarni avtomatik bloklaydi
sudo apt install fail2ban -yBu to'liq security audit emas, lekin real hujumlarning katta qismini aynan shu baza to'xtatadi.
Node.js app — systemd service sifatida
Ko'pchilik pm2'dan boshlaydi, bu yomon emas. Lekin serverda allaqachon professional process manager bor — systemd. U OS bilan birga keladi, alohida daemon talab qilmaydi, loglari journald'da to'planadi va server qayta yonganda servisni o'zi ko'taradi. pm2 esa cluster mode yoki o'z monitoring interfeysi kerak bo'lganda asqotadi. Bitta app uchun systemd sodda va yetarli.
/etc/systemd/system/myapp.service fayli:
[Unit]
Description=My Node.js app
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy/myapp
ExecStart=/usr/bin/node dist/server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
EnvironmentFile=/home/deploy/myapp/.env
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now myapp
journalctl -u myapp -f # loglarni jonli kuzatishRestart=always tufayli app crash bo'lsa, 5 soniyada o'zi qayta ko'tariladi — tungi qo'ng'iroqlar kamayadi.
nginx: reverse proxy, gzip va static cache
App 3000-portda ishlaydi, dunyoga esa 80/443 orqali nginx ko'rinadi. /etc/nginx/sites-available/myapp:
server {
listen 80;
server_name example.uz;
gzip on;
gzip_types text/css application/javascript application/json;
# Static fayllarni nginx o'zi beradi — app'ga yuk tushmaydi
location /static/ {
alias /home/deploy/myapp/public/;
expires 30d;
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-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}Tekshirish va yoqish: sudo nginx -t && sudo systemctl reload nginx.
HTTPS: certbot bilan 2 daqiqada
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.uzcertbot nginx konfigni o'zi yangilaydi va sertifikatni muddati tugashidan oldin avtomatik uzaytiradi. "SSL qimmat va mashaqqatli" degan davr allaqachon o'tgan — bugun HTTPS bepul va majburiy standart.
Zero-downtime yangilash — eng sodda usul
Murakkab orkestratsiya shart emas. Oddiy deploy skript:
#!/usr/bin/env bash
set -e
cd /home/deploy/myapp
git pull origin main
npm ci --omit=dev
npm run build
sudo systemctl restart myapp
# Health check: app javob berguncha kutamiz
for i in {1..10}; do
sleep 2
curl -fs http://127.0.0.1:3000/health && echo "Deploy OK" && exit 0
done
echo "Deploy FAILED" && exit 1Bu usulda 2–3 soniya uzilish bo'ladi — ko'pchilik loyiha uchun foydalanuvchi buni sezmaydi ham. Haqiqiy zero-downtime kerak bo'lsa, yangi versiyani yonma-yon 3001-portda ko'tarasiz, health check o'tgach nginx'dagi proxy_pass portini almashtirib reload qilasiz — nginx reload aktiv ulanishlarni uzmaydi. Ikkala usul ham bitta bash skriptga sig'adi, Kubernetes bu bosqichda kerak emas.
Docker kerakmi?
Pragmatik javob: boshida — yo'q. Bitta Node app va bitta Postgres uchun Docker qo'shimcha qatlam: image build, volume, network — o'rganish yuki ortadi, foyda esa hali ko'rinmaydi. Docker qachon o'zini oqlaydi:
- Loyihada mos kelmaydigan runtime'lar bo'lsa (turli Node yoki Python versiyalari)
- Bir xil muhitni bir nechta serverga ko'chirish kerak bo'lsa
- Jamoa kattalashib, "menda ishlayapti-ku" muammosi qimmatga tusha boshlasa
Men maktab tizimlarida Docker'ni aynan ikkinchi sabab uchun ishlataman: bitta tizimni o'nlab serverga bir xil holatda yoyish kerak. Bitta VPS'dagi bitta loyihada esa systemd + nginx to'liq yetarli.
Backup: eng oddiy cron + pg_dump
Backup'siz production — sekin ishlaydigan vaqt bombasi. Eng oddiy ishlaydigan sxema:
# /home/deploy/backup.sh
#!/usr/bin/env bash
set -e
DIR=/home/deploy/backups
DATE=$(date +%F)
pg_dump -U myapp mydb | gzip > "$DIR/db-$DATE.sql.gz"
# 14 kundan eski nusxalarni o'chirish
find "$DIR" -name "db-*.sql.gz" -mtime +14 -delete# crontab -e — har kuni soat 03:00 da
0 3 * * * /home/deploy/backup.sh >> /home/deploy/backup.log 2>&1Muhim qoida: backup faqat serverning o'zida tursa, u backup emas. Hech bo'lmasa haftada bir marta nusxani boshqa joyga — boshqa server, object storage yoki hatto shaxsiy kompyuteringizga ko'chiring. Va yiliga bir-ikki marta restore qilib ko'ring: tiklab bo'lmaydigan backup'ning hech qanday foydasi yo'q.
Xulosa
VPS'da deploy — bir marta o'rganiladigan hunar: SSH kalit, ufw, systemd unit, nginx konfig, certbot, oddiy deploy skript va cron backup. Shu yetti qadam bilan loyihangiz professional darajada, barqaror ishlaydi. Keyin loyiha o'ssa, ustiga CI/CD, monitoring, kerak bo'lsa Docker qo'shasiz — lekin poydevor shu bo'lib qolaveradi.