Django loyihasini ishlab chiqish paytida python manage.py runserver juda qulay, lekin u faqat sinov uchun mo'ljallangan. Bu server bir vaqtda ko'p so'rovni yaxshi ko'tarmaydi, xavfsizlik bo'yicha tekshirilmagan va statik fayllarni samarali bermaydi. Haqiqiy saytda vazifalar ikkiga bo'linadi: Gunicorn Python kodini bajaradi, Nginx esa tashqi dunyo bilan gaplashadi, ya'ni HTTPS, statik fayllar va sekin mijozlarni o'z zimmasiga oladi. Quyida Ubuntu o'rnatilgan VPS'da shunday tuzilmani noldan yig'ib chiqamiz.
Tuzilma: so'rov qanday yo'l bosib o'tadi
Foydalanuvchi brauzeri misol.uz saytiga murojaat qilganda so'rov avval Nginx'ga keladi. Agar bu /static/ yoki /media/ manzili bo'lsa, Nginx faylni diskdan o'zi beradi va Python'ga umuman tegmaydi. Qolgan so'rovlar Unix soket orqali Gunicorn'ga uzatiladi. Gunicorn bir nechta ishchi jarayon ochib, har birida Django ilovasini WSGI interfeysi orqali ishga tushiradi. Bu ajratish tufayli sekin internetli foydalanuvchi Python ishchisini band qilib turmaydi, chunki javobni oxirigacha yetkazish bilan Nginx shug'ullanadi.
Misol sifatida Samarqanddagi xususiy maktabning misol.uz saytini olaylik. Saytda yangiliklar, dars jadvali va o'qituvchilar uchun Django admin paneli bor. Ota-onalar ertalab bir vaqtda jadvalni ochishadi, shuning uchun saytga qisqa vaqt ichida ko'p so'rov tushadi. Quyidagi sozlama aynan shunday yuklamani bemalol ko'taradi.
Serverni va virtual muhitni tayyorlash
Avval kerakli paketlarni o'rnatamiz va loyiha uchun alohida tizim foydalanuvchisi yaratamiz. Ilovani root nomidan ishlatish xavfli: koddagi bitta zaiflik butun serverni boshqarishga yo'l ochib beradi.
sudo apt update
sudo apt install python3-venv python3-pip nginx
sudo adduser --system --group --home /srv/misol misol
sudo -u misol python3 -m venv /srv/misol/venv
sudo -u misol /srv/misol/venv/bin/pip install -r /srv/misol/requirements.txt gunicorn
Loyiha kodi /srv/misol papkasida, Django sozlamalari esa config paketida joylashgan deb hisoblaymiz. Sizda bu paket nomi boshqacha bo'lsa, keyingi buyruqlarda config.wsgi o'rniga o'z nomingizni yozing.
Django sozlamalarini ishlab chiqarishga moslash
settings.py faylida bir nechta qiymat albatta o'zgarishi kerak. Maxfiy kalit va parollar kodda emas, muhit o'zgaruvchilarida saqlanadi, shunda ular Git tarixiga tushib qolmaydi.
import os
DEBUG = False
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
ALLOWED_HOSTS = ["misol.uz", "www.misol.uz"]
CSRF_TRUSTED_ORIGINS = ["https://misol.uz", "https://www.misol.uz"]
STATIC_URL = "/static/"
STATIC_ROOT = "/srv/misol/staticfiles"
MEDIA_URL = "/media/"
MEDIA_ROOT = "/srv/misol/media"
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
DEBUG = False bo'lganda Django statik fayllarni o'zi bermaydi, shuning uchun ularni bitta papkaga yig'ib, Nginx'ga topshiramiz. SECURE_PROXY_SSL_HEADER esa Django'ga so'rov aslida HTTPS orqali kelganini bildiradi, aks holda xavfsiz cookie va yo'naltirishlar noto'g'ri ishlaydi. Endi migratsiya va statik fayllarni yig'ish buyruqlarini bajaring:
sudo -u misol /srv/misol/venv/bin/python /srv/misol/manage.py migrate
sudo -u misol /srv/misol/venv/bin/python /srv/misol/manage.py collectstatic --noinput
Gunicorn'ni systemd xizmati sifatida ishga tushirish
Gunicorn'ni terminalda qo'lda ochish yetarli emas: SSH sessiyasi yopilganda yoki server qayta yuklanganda u to'xtaydi. Shuning uchun uni systemd xizmati qilib ro'yxatdan o'tkazamiz. /etc/systemd/system/misol.service faylini yarating:
[Unit]
Description=Gunicorn for misol.uz
After=network.target
[Service]
User=misol
Group=www-data
WorkingDirectory=/srv/misol
EnvironmentFile=/srv/misol/.env
RuntimeDirectory=misol
ExecStart=/srv/misol/venv/bin/gunicorn --workers 3 --bind unix:/run/misol/gunicorn.sock --umask 007 config.wsgi:application
Restart=on-failure
[Install]
WantedBy=multi-user.target
RuntimeDirectory har ishga tushishda /run/misol papkasini yaratadi, Group=www-data va --umask 007 esa soketga Nginx guruhining yozish huquqini beradi. Ishchilar sonini odatda protsessor yadrolari soniga qarab tanlashadi; ikki yadroli server uchun 3-5 ishchi yaxshi boshlang'ich nuqta. .env faylida DJANGO_SECRET_KEY=... kabi qatorlar turadi va uni faqat misol foydalanuvchisi o'qiy olishi kerak. Xizmatni yoqing va holatini tekshiring:
sudo systemctl daemon-reload
sudo systemctl enable --now misol
sudo systemctl status misol
Nginx'ni teskari proksi sifatida sozlash
/etc/nginx/sites-available/misol faylini yarating. Unda statik va media fayllar to'g'ridan-to'g'ri diskdan beriladi, qolgan so'rovlar Gunicorn soketiga uzatiladi:
server {
listen 80;
server_name misol.uz www.misol.uz;
client_max_body_size 20M;
location /static/ {
alias /srv/misol/staticfiles/;
}
location /media/ {
alias /srv/misol/media/;
}
location / {
proxy_pass http://unix:/run/misol/gunicorn.sock;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
sudo ln -s /etc/nginx/sites-available/misol /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d misol.uz -d www.misol.uz
Certbot Let's Encrypt sertifikatini olib, Nginx konfiguratsiyasiga HTTPS blokini o'zi qo'shadi va avtomatik yangilanishni ham sozlaydi. Bu bosqichdan oldin domenning A yozuvi VPS manziliga ishora qilishi shart; sayt.uz kabinetidagi DNS bo'limida buni oldindan tekshirib qo'ying.
502 Bad Gateway va boshqa tipik xatolar
Eng ko'p uchraydigan xato bu 502 Bad Gateway bo'lib, u Nginx Gunicorn bilan bog'lana olmaganini anglatadi. Avval sudo journalctl -u misol -n 50 bilan xizmat loglarini ko'ring: ko'pincha import xatosi, yetishmayotgan muhit o'zgaruvchisi yoki noto'g'ri config.wsgi yo'li sabab bo'ladi. Agar xizmat ishlab turgan bo'lsa, soketga ruxsatni tekshiring, Nginx xatolar logida Permission denied qatori bo'lsa, guruh yoki umask noto'g'ri. Statik fayllar 404 bersa, collectstatic bajarilganini va Nginx foydalanuvchisi /srv/misol/staticfiles papkasini o'qiy olishini tekshiring.
Kodni yangilash har safar bir xil tartibda bajariladi: yangi kodni olish, bog'liqliklarni o'rnatish, migratsiya, statik fayllarni yig'ish va xizmatni qayta ishga tushirish. Bu qadamlarni kichik skriptga yozib qo'ysangiz, maktab sayti yangilanishlari har safar xatosiz va bir xil o'tadi.
cd /srv/misol && sudo -u misol git pull
sudo -u misol venv/bin/pip install -r requirements.txt
sudo -u misol venv/bin/python manage.py migrate
sudo -u misol venv/bin/python manage.py collectstatic --noinput
sudo systemctl restart misol