17-bo‘lim
Nginx - statik fayllar va teskari proksi
server bloklari, location tartibi, proxy_pass, 502 xatosining sababi va veb-server darajasidagi himoya.
Ushbu bo‘lim mundarijasi
Nginx serverda ikkita ish bajaradi: statik fayllarni
juda tez uzatadi va ilovaga so'rovlarni yo'naltiradi.
Ilova esa 127.0.0.1 da yashirinib turadi.
Nima uchun ilova to'g'ridan-to'g'ri turmasin #
| Vazifa | Ilova o'zi | Nginx orqali |
|---|---|---|
| Statik fayl uzatish | Sekin | Juda tez |
| TLS | Har ilovada alohida | Bir joyda (18-bo'lim) |
| Bir necha domen | Qiyin | server bloklari |
| Sekin mijozlar | Ilova oqimini band qiladi | Nginx buferlaydi |
| Tezlik cheklovi | Kodda yozasiz | limit_req |
| Ilova qayta ishga tushganda | Xato sahifa | Nginx 502 beradi |
Sinov muhiti #
Bu bo'limda Nginx alohida prefiks bilan, 127.0.0.1:8088
da ishga tushiriladi - tizimdagi Nginx sozlamasiga tegilmaydi.
[ -f logs/nginx.pid ] && kill -QUIT "$(cat logs/nginx.pid)" 2>/dev/null
sleep 0.3
mkdir -p conf logs html temp api
echo "<h1>Statik sahifa</h1>" > html/index.html
echo "SIRLI_KALIT=12345" > html/.env
echo '{"holat": "ok"}' > api/holat.json
cat > conf/nginx.conf <<'EOF'
worker_processes 1;
error_log logs/error.log warn;
pid logs/nginx.pid;
events { worker_connections 64; }
http {
access_log logs/access.log;
client_body_temp_path temp;
proxy_temp_path temp/proxy;
fastcgi_temp_path temp/fastcgi;
uwsgi_temp_path temp/uwsgi;
scgi_temp_path temp/scgi;
default_type text/html;
server {
listen 127.0.0.1:8088;
server_name localhost;
root html;
location / {
try_files $uri $uri/ =404;
}
location /api/ {
proxy_pass http://127.0.0.1:8081/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ~ /\. {
deny all;
}
}
}
EOF
Sozlamani tekshirish #
nginx -p "$PWD" -c conf/nginx.conf -t 2>&1 | sed "s|$PWD/||g"
nginx: the configuration file conf/nginx.conf syntax is ok
nginx: configuration file conf/nginx.conf test is successful
Xato sozlama qanday ko'rinadi:
printf 'events {}\nhttp { server { listen 8088 } }\n' > conf/yomon.conf
nginx -p "$PWD" -c conf/yomon.conf -t 2>&1 \
| sed "s|$PWD/||g; s/^[0-9\/]* [0-9:]* //; s/[0-9]*#[0-9]*: //"
[emerg] unexpected "}" in conf/yomon.conf:2
nginx: configuration file conf/yomon.conf test failed
listen 8088 dan keyin nuqta-vergul tushib qolgan.
nginx -t siz reload qilmangAgar sozlamada xato bo'lsa:
| Buyruq | Natija |
|---|---|
systemctl reload nginx | Nginx eski sozlama bilan ishlashda davom etadi |
systemctl restart nginx | Nginx butunlay to'xtaydi - sayt o'chadi |
Ikkinchisi - kechqurun sayt yo'qolishining eng ko'p uchraydigan sababi.
Shuning uchun tartib doim shunday:
sudo nginx -t && sudo systemctl reload nginx
&& muhim: nginx -t xato bersa, reload umuman
bajarilmaydi.
Bu darslikdagi beshinchi "avval tekshir" buyrug'i:
visudo -c, sshd -t, systemd-analyze verify, nft -c -f
va nginx -t.
Statik fayllar #
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -s http://127.0.0.1:8088/
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8088/mavjud-emas
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
<h1>Statik sahifa</h1>
404
| Direktiva | Vazifa |
|---|---|
root html | Fayllar qayerdan olinadi |
index index.html | Katalog so'ralganda qaysi fayl |
try_files $uri $uri/ =404 | Ketma-ket urinish, topilmasa 404 |
autoindex on | Katalog ro'yxatini ko'rsatish - odatda kerak emas |
root va alias farqiBu ikkisi juda o'xshash ko'rinadi, lekin boshqacha ishlaydi:
location /rasm/ {
root /var/www/sayt; # -> /var/www/sayt/rasm/logo.png
}
location /rasm/ {
alias /var/www/rasmlar/; # -> /var/www/rasmlar/logo.png
}
root da location yo'li yo'lga qo'shiladi, alias da
esa almashtiriladi.
Amaliy maslahat: iloji boricha root ishlating. alias
bilan bitta klassik xato bor - oxirgi / ni unutish:
location /rasm {
alias /var/www/rasmlar; # XAVFLI
}
Bunda /rasm../etc/passwd kabi so'rov katalogdan tashqariga
chiqishi mumkin. alias ishlatsangiz, location ham, alias
ham / bilan tugasin.
Teskari proksi #
(cd api && exec python3 -m http.server 8081 --bind 127.0.0.1 >/dev/null 2>&1) &
BE=$!
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -s http://127.0.0.1:8088/api/holat.json
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
kill "$BE" 2>/dev/null
{"holat": "ok"}
So'rov 8088 ga keldi, Nginx uni 8081 dagi ilovaga uzatdi
va javobni qaytardi.
proxy_pass da oxirgi / hamma narsani o'zgartiradilocation /api/ {
proxy_pass http://127.0.0.1:8081/; # / BOR
}
/api/holat.json → ilovaga /holat.json bo'lib boradi.
/api/ qismi kesib tashlanadi.
location /api/ {
proxy_pass http://127.0.0.1:8081; # / YO'Q
}
/api/holat.json → ilovaga /api/holat.json bo'lib boradi.
Yo'l to'liq uzatiladi.
Ikkalasi ham to'g'ri bo'lishi mumkin - bu ilova nimani kutayotganiga bog'liq. Lekin ularni chalkashtirish 404 xatolarining eng ko'p uchraydigan sababi.
Shubha bo'lsa, ilova jurnaliga qarang: u qaysi yo'lni olganini yozadi.
Uzatiladigan sarlavhalar #
proxy_set_header bo'lmasa, ilova mijoz haqida hech nima
bilmaydi.
| Sarlavha | Nima uchun kerak |
|---|---|
Host $host | Ilova qaysi domen so'ralganini biladi |
X-Real-IP $remote_addr | Mijozning haqiqiy IP manzili |
X-Forwarded-For $proxy_add_x_forwarded_for | Proksilar zanjiri |
X-Forwarded-Proto $scheme | HTTP mi, HTTPS mi |
X-Forwarded-For ga ishonmangBu sarlavhani mijoz o'zi ham yubora oladi. Agar ilovangiz uni to'g'ridan-to'g'ri o'qisa, hujumchi istalgan IP ni ko'rsata oladi - va IP bo'yicha bloklash, tezlik cheklovi hamda jurnal ishonchsiz bo'lib qoladi.
To'g'ri yondashuv:
| Qadam | Nima qilinadi |
|---|---|
| Nginx sarlavhani o'zi qo'yadi | X-Real-IP $remote_addr |
| Ilova faqat Nginx dan kelganiga ishonadi | Ilova 127.0.0.1 da tinglaydi |
| Bir necha proksi bo'lsa | set_real_ip_from bilan ishonchli manbalarni sanang |
Uchinchisi muhim: Cloudflare yoki yuk balanslagichi ortida turgan bo'lsangiz, faqat o'sha manzillardan kelgan sarlavhaga ishoning:
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
502 Bad Gateway - eng ko'p uchraydigan xato #
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8088/api/holat.json
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
502
Backend ishga tushirilmagan - va Nginx 502 qaytardi.
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -s -o /dev/null http://127.0.0.1:8088/api/holat.json
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
sleep 0.3
grep -o 'connect() failed ([0-9]*: [^)]*)' logs/error.log | tail -1
connect() failed (111: Connection refused)
502, 504, 503 - uchta boshqa sabab| Kod | Ma'no | Odatiy sabab |
|---|---|---|
502 Bad Gateway | Backend javob bermadi | Ilova o'lgan yoki port noto'g'ri |
504 Gateway Timeout | Backend juda sekin | So'rov proxy_read_timeout dan uzoq |
503 Service Unavailable | Nginx o'zi rad etdi | limit_req yoki upstream da server yo'q |
Farqni bilish tashxisni tezlashtiradi:
| Kod | Qayerga qarash |
|---|---|
502 | systemctl status ilova, ss -tlnp |
504 | Ilova jurnali - qaysi so'rov osilib qolgan |
503 | Nginx sozlamasi - cheklovlar |
error.log dagi raqamli kod ham aniq aytadi: 111 -
Connection refused (hech kim tinglamayapti), 110 -
Connection timed out (javob yo'q).
Veb-server darajasidagi himoya #
nginx -p "$PWD" -c conf/nginx.conf
sleep 1
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8088/.env
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8088/index.html
nginx -p "$PWD" -c conf/nginx.conf -s quit 2>/dev/null
403
200
.env fayli diskda bor, lekin Nginx uni bermadi.
.env va .git - internetdagi eng ko'p skanerlanadigan yo'llarAvtomatik skanerlar har yangi domenni topgach, birinchi navbatda shu yo'llarni sinaydi:
| Yo'l | Ichida nima bo'lishi mumkin |
|---|---|
/.env | Ma'lumotlar bazasi paroli, API kalitlari |
/.git/config | Ombor manzili, ba'zan token |
/.git/HEAD | Butun manba kodini yuklab olish mumkin |
/backup.sql, /dump.sql | To'liq ma'lumotlar bazasi |
/.DS_Store | Fayllar ro'yxati |
Ikkita qatlam himoya:
location ~ /\. {
deny all;
access_log off;
}
location ~* \.(sql|bak|old|log)$ {
deny all;
}
Va eng muhimi: bu fayllar root katalogida umuman
bo'lmasin. Ilova kodini /var/www/sayt ga, ochiq fayllarni
esa /var/www/sayt/public ga qo'ying va root ni aynan
public ga qarating.
Nginx qoidasi - ikkinchi himoya qatlami, birinchisi emas.
Foydali sozlamalar #
| Direktiva | Vazifa |
|---|---|
gzip on | Javobni siqish - trafik kamayadi |
client_max_body_size 20m | Yuklanadigan fayl chegarasi |
proxy_read_timeout 60s | Backend javobini kutish vaqti |
expires 30d | Statik fayllar uchun kesh |
server_tokens off | Versiya raqamini yashirish |
limit_req_zone | Tezlik cheklovi |
add_header X-Frame-Options DENY | Xavfsizlik sarlavhalari |
client_max_body_size - "413" xatosining sababiStandart qiymat 1 MB. Foydalanuvchi 2 MB lik rasm
yuklamoqchi bo'lsa, Nginx 413 Request Entity Too Large
qaytaradi - ilova bu haqda umuman bilmaydi.
Bu xato ko'pincha ilovada qidiriladi, aslida esa Nginx darajasida hal qilinadi:
client_max_body_size 20m;
PHP ishlatilsa, uchta joyda birga oshirish kerak:
| Joy | Sozlama |
|---|---|
| Nginx | client_max_body_size |
| PHP | upload_max_filesize |
| PHP | post_max_size |
Uchtasidan eng kichigi amal qiladi. Bittasini oshirib, qolganini unutish - klassik vaqt yo'qotish.
Bir necha sayt #
server {
listen 80;
server_name softromeda.uz www.softromeda.uz;
return 301 https://softromeda.uz$request_uri;
}
server {
listen 443 ssl;
server_name softromeda.uz;
root /var/www/softromeda/public;
}
server {
listen 443 ssl;
server_name edu.softromeda.uz;
root /var/www/edu/public;
}
Nginx Host sarlavhasiga qarab qaysi server blokini
ishlatishni tanlaydi.
server bloki - so'ralmagan domenlar uchunAgar hech bir server_name mos kelmasa, Nginx birinchi
blokni ishlatadi. Bu kutilmagan natija beradi: serveringizning
IP manzilini bilgan har kim tasodifiy saytingizni ko'radi.
To'g'risi - aniq "hech kim" bloki qo'shish:
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
return 444;
}
444 - Nginx ning maxsus kodi: javob bermasdan ulanishni
yopish. Skanerlar hech qanday ma'lumot olmaydi.
Sozlama fayllarini /etc/nginx/sites-available/ da saqlang
va sites-enabled/ ga havola qo'ying - shunda saytni
o'chirmasdan vaqtincha yopish mumkin:
sudo rm /etc/nginx/sites-enabled/sayt
sudo nginx -t && sudo systemctl reload nginx
Jurnallar #
| Fayl | Ichida nima |
|---|---|
/var/log/nginx/access.log | Har so'rov |
/var/log/nginx/error.log | Xatolar va ogohlantirishlar |
3-bo'limdagi iboralar aynan shu yerda ishlaydi:
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
awk '$9 == 404 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
awk '$9 >= 500 {print}' /var/log/nginx/access.log | tail -20
- Alohida prefiks bilan Nginx sozlamasi yozing.
nginx -tbilan tekshiring, keyin ataylab xato kiriting.- Statik faylni uzating va 404 ni oling.
proxy_passbilan backendga yo'naltiring.- Backendni to'xtatib,
502ni oling. error.logdanconnect() failedsatrini toping.location ~ /.bilan.envni bloklang va403ni tasdiqlang.proxy_passda oxirgi/bor va yo'q holatlarni solishtiring.default_serverbloki bilan444qaytaring.access.logdan eng ko'p 404 bergan yo'llarni sanang.
Xulosa #
- Nginx statikni tez uzatadi, ilovani
127.0.0.1da yashiradi. nginx -t && systemctl reload nginx-&&ni tushirmang.restartsaytni o'chiradi,reloadesa uzmaydi.rootyo'lni qo'shadi,aliasalmashtiradi.proxy_passdagi oxirgi/yo'lni kesadi - 404 larning tez-tez sababi.X-Forwarded-Forga ishonmang;X-Real-IPni Nginx o'zi qo'ysin.502- backend o'lgan,504- sekin,503- Nginx rad etdi..envva.gitni bloklang, lekin ularnirootga umuman qo'ymang.client_max_body_sizestandart holda atigi 1 MB.default_server+return 444- so'ralmagan domenlarga javob bermaslik.
Keyingi bo'limda HTTPS ni yoqamiz: sertifikatlar, Let's Encrypt va TLS sozlamalari.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.