Django лойиҳасини ишлаб чиқиш пайтида python manage.py runserver жуда қулай, лекин у фақат синов учун мўлжалланган. Бу сервер бир вақтда кўп сўровни яхши кўтармайди, хавфсизлик бўйича текширилмаган ва статик файлларни самарали бермайди. Ҳақиқий сайтда вазифалар иккига бўлинади: Gunicorn Python кодини бажаради, Nginx эса ташқи дунё билан гаплашади, яъни HTTPS, статик файллар ва секин мижозларни ўз зиммасига олади. Қуйида Ubuntu ўрнатилган VPS'да шундай тузилмани нолдан йиғиб чиқамиз.
Тузилма: сўров қандай йўл босиб ўтади
Фойдаланувчи браузери misol.uz сайтига мурожаат қилганда сўров аввал Nginx'га келади. Агар бу /static/ ёки /media/ манзили бўлса, Nginx файлни дискдан ўзи беради ва Python'га умуман тегмайди. Қолган сўровлар Уних сокет орқали Gunicorn'га узатилади. Gunicorn бир нечта ишчи жараён очиб, ҳар бирида Django иловасини WSGI интерфейси орқали ишга туширади. Бу ажратиш туфайли секин интернетли фойдаланувчи Python ишчисини банд қилиб турмайди, чунки жавобни охиригача етказиш билан Nginx шуғулланади.
Мисол сифатида Самарқанддаги хусусий мактабнинг misol.uz сайтини олайлик. Сайтда янгиликлар, дарс жадвали ва ўқитувчилар учун Django admin панели бор. Ота-оналар эрталаб бир вақтда жадвални очишади, шунинг учун сайтга қисқа вақт ичида кўп сўров тушади. Қуйидаги созлама айнан шундай юкламани бемалол кўтаради.
Серверни ва виртуал муҳитни тайёрлаш
Аввал керакли пакетларни ўрнатамиз ва лойиҳа учун алоҳида тизим фойдаланувчиси яратамиз. Иловани root номидан ишлатиш хавфли: коддаги битта заифлик бутун серверни бошқаришга йўл очиб беради.
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
Лойиҳа коди /srv/misol папкасида, Django созламалари эса config пакетида жойлашган деб ҳисоблаймиз. Сизда бу пакет номи бошқача бўлса, кейинги буйруқларда config.wsgi ўрнига ўз номингизни ёзинг.
Django созламаларини ишлаб чиқаришга мослаш
settings.py файлида бир нечта қиймат албатта ўзгариши керак. Махфий калит ва пароллар кодда эмас, муҳит ўзгарувчиларида сақланади, шунда улар Git тарихига тушиб қолмайди.
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 бўлганда Django статик файлларни ўзи бермайди, шунинг учун уларни битта папкага йиғиб, Nginx'га топширамиз. SECURE_PROXY_SSL_HEADER эса Django'га сўров аслида HTTPS орқали келганини билдиради, акс ҳолда хавфсиз cookie ва йўналтиришлар нотўғри ишлайди. Энди миграция ва статик файлларни йиғиш буйруқларини бажаринг:
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'ни systemd хизмати сифатида ишга тушириш
Gunicorn'ни терминалда қўлда очиш етарли эмас: SSH сессияси ёпилганда ёки сервер қайта юкланганда у тўхтайди. Шунинг учун уни systemd хизмати қилиб рўйхатдан ўтказамиз. /etc/systemd/system/misol.service файлини яратинг:
[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 ҳар ишга тушишда /run/misol папкасини яратади, Group=www-data ва --umask 007 эса сокетга Nginx гуруҳининг ёзиш ҳуқуқини беради. Ишчилар сонини одатда процессор ядролари сонига қараб танлашади; икки ядроли сервер учун 3-5 ишчи яхши бошланғич нуқта. .env файлида DJANGO_SECRET_KEY=... каби қаторлар туради ва уни фақат misol фойдаланувчиси ўқий олиши керак. Хизматни ёқинг ва ҳолатини текширинг:
sudo systemctl daemon-reload
sudo systemctl enable --now misol
sudo systemctl status misol
Nginx'ни тескари прокси сифатида созлаш
/etc/nginx/sites-available/misol файлини яратинг. Унда статик ва медиа файллар тўғридан-тўғри дискдан берилади, қолган сўровлар Gunicorn сокетига узатилади:
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 сертификатини олиб, Nginx конфигурациясига HTTPS блокини ўзи қўшади ва автоматик янгиланишни ҳам созлайди. Бу босқичдан олдин доменнинг A ёзуви VPS манзилига ишора қилиши шарт; sayt.uz кабинетидаги DNS бўлимида буни олдиндан текшириб қўйинг.
502 Bad Gateway ва бошқа типик хатолар
Энг кўп учрайдиган хато бу 502 Bad Gateway бўлиб, у Nginx Gunicorn билан боғлана олмаганини англатади. Аввал sudo journalctl -u misol -n 50 билан хизмат логларини кўринг: кўпинча импорт хатоси, етишмаётган муҳит ўзгарувчиси ёки нотўғри config.wsgi йўли сабаб бўлади. Агар хизмат ишлаб турган бўлса, сокетга рухсатни текширинг, Nginx хатолар логида Permission denied қатори бўлса, гуруҳ ёки умаск нотўғри. Статик файллар 404 берса, collectstatic бажарилганини ва Nginx фойдаланувчиси /srv/misol/staticfiles папкасини ўқий олишини текширинг.
Кодни янгилаш ҳар сафар бир хил тартибда бажарилади: янги кодни олиш, боғлиқликларни ўрнатиш, миграция, статик файлларни йиғиш ва хизматни қайта ишга тушириш. Бу қадамларни кичик скриптга ёзиб қўйсангиз, мактаб сайти янгиланишлари ҳар сафар хатосиз ва бир хил ўтади.
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