- LoopX
- Nginx کاربردی
- دستورات و تنظیمات Nginx: برگهی تقلب کامل
دستورات و تنظیمات Nginx: برگهی تقلب کامل
همهی دستورهای دورهی Nginx کاربردی در یک صفحه: ۱۷۹ دستور از ۱۶ درس، به ترتیب درسها. هر دستور در درس خودش با خروجی واقعی اجرا و توضیح داده شده است؛ روی اسم درس بزن تا توضیح کامل و مثالها را ببینی.
مبانی
Nginx چیست؟
| دستور | کاری که میکند |
|---|---|
nginx -v | نسخهی Nginx |
nginx -V 2>&1 | grep -o -- "--with-[a-z0-9_]*" | ماژولهای build شده |
curl -i http://localhost/ | پاسخ کامل با هدرها |
curl -sI https://site | grep -i ^server | وبسرور یک سایت (فقط هدرها) |
curl -s -o /dev/null -w "%{http_code}\n" URL | فقط کد وضعیت |
nginx -t && systemctl reload nginx | آزمایش و اعمال تنظیمات |
proxy_pass http://127.0.0.1:9001; | reverse proxy به یک اپ |
upstream app { server a; server b; } | گروه سرورها برای load balancing |
ps -o pid,user,cmd -C nginx | master و worker ها |
ab -n 2000 -c 50 URL | آزمایش بار ساده |
نصب و اجرا
| دستور | کاری که میکند |
|---|---|
sudo apt install nginx | نصب روی Ubuntu |
apt-cache policy nginx | نسخهی موجود در مخزن |
sudo systemctl status nginx | وضعیت و چند خط آخر لاگ |
sudo systemctl enable --now nginx | فعال در بوت و شروع همین الان |
sudo nginx -t && sudo systemctl reload nginx | آزمایش و اعمال امن تنظیمات |
sudo journalctl -u nginx --no-pager | tail | لاگ سرویس برای عیبیابی |
sudo dpkg --configure -a | کامل کردن نصب نیمهکاره |
sudo ss -tlnp "sport = :80" | چه کسی پورت ۸۰ را گرفته؟ |
sudo ufw allow 'Nginx Full' | باز کردن ۸۰ و ۴۴۳ در فایروال |
docker run -d -p 8080:80 nginx:alpine | Nginx در داکر |
docker run -d -p 8091:80 -v "$PWD/site:/usr/share/nginx/html:ro" nginx:alpine | سرو کردن پوشهی خودت |
docker exec CONTAINER nginx -s reload | reload داخل کانتینر |
ساختار فایلهای تنظیمات
| دستور | کاری که میکند |
|---|---|
sudo nginx -t | آزمایش تنظیمات، با فایل و شمارهی خط خطا |
sudo nginx -T | grep '^# configuration file' | فایلهایی که واقعاً خوانده میشوند |
sudo systemctl reload nginx | اعمال تنظیمات بدون قطع |
sudo ln -s /etc/nginx/sites-available/shop.test /etc/nginx/sites-enabled/ | روشن کردن یک سایت |
sudo rm /etc/nginx/sites-enabled/shop.test | خاموش کردن سایت |
ls -l /etc/nginx/sites-enabled/ | سایتهای فعال (باید -> نشان دهد) |
include snippets/headers.conf; | آوردن یک تکهی مشترک |
return 200 "ok\n"; | پاسخ مستقیم بدون فایل |
curl --resolve shop.test:80:127.0.0.1 http://shop.test/ | آزمایش یک دامنه بدون DNS |
grep -nvE '^\s*(#|$)' /etc/nginx/nginx.conf | خواندن فایل بدون کامنت |
server block و چند سایت
| دستور | کاری که میکند |
|---|---|
server { listen 80; server_name shop.test; root /var/www/shop.test; index index.html; } | یک سایت |
listen 80 default_server; server_name _; return 444; | catch-all برای دامنههای ناشناخته |
server_name shop.test www.shop.test; | چند اسم برای یک سایت |
server_name *.shop.test; | همهی زیردامنهها |
server_name ~^(?<user>[a-z0-9-]+)\.sites\.test$; | regex با گروه نامدار |
return 301 http://shop.test$request_uri; | ریدایرکت با حفظ مسیر |
listen 127.0.0.1:8087; | فقط داخلی |
echo "127.0.0.1 shop.test" | sudo tee -a /etc/hosts | دامنهی محلی برای آزمایش |
curl -H "Host: shop.test" http://127.0.0.1/ | آزمایش با هدر Host دلخواه |
curl -sv http://shop.test/ 2>&1 | grep '^> Host' | دیدن هدر Host فرستادهشده |
add_header X-Debug-Server $server_name always; | کدام block جواب داد؟ |
location و مسیرها
| دستور | کاری که میکند |
|---|---|
location = /health { return 200 "ok\n"; } | تطبیق دقیق |
location /api/ { proxy_pass http://127.0.0.1:3000; } | پیشوندی: همهی /api/... |
location ^~ /static/ { ... } | پیشوندی که regex را کنار میزند |
location ~* \.(jpg|png|webp)$ { ... } | regex بدون حساسیت به حروف |
try_files $uri $uri/ =404; | سایت استاتیک |
try_files $uri $uri.html $uri/ =404; | آدرس بدون .html |
try_files $uri @app; | نبود؟ برو به named location |
location /static/ { root /srv; } | /static/a ← /srv/static/a |
location /static/ { alias /srv/assets/; } | /static/a ← /srv/assets/a (اسلشها هماهنگ) |
add_header X-Matched "name" always; | کدام location جواب داد؟ |
curl --path-as-is "http://site/a/../b" | فرستادن مسیر بدون نرمالسازی curl |
سرو سایت استاتیک
| دستور | کاری که میکند |
|---|---|
try_files $uri $uri/ =404; | سایت چندصفحهای |
error_page 404 /404.html; | صفحهی ۴۰۴ سفارشی با کد ۴۰۴ |
error_page 500 502 503 504 /50x.html; | صفحهی خطای سرور |
location ^~ /errors/ { internal; } | بستن دسترسی مستقیم به صفحههای خطا |
location / { try_files $uri $uri/ /index.html; } | SPA fallback |
location /assets/ { try_files $uri =404; } | ۴۰۴ واقعی برای داراییهای SPA |
location /downloads/ { alias /srv/downloads/; autoindex on; } | فهرست پوشهی دانلود |
location ~ /\.(?!well-known) { deny all; } | بستن .git، .env و فایلهای مخفی |
curl -s -o /dev/null -w '%{http_code} %{content_type}' URL | کد و نوع پاسخ |
curl -H "If-None-Match: $etag" URL | آزمایش 304 |
لاگها
| دستور | کاری که میکند |
|---|---|
sudo tail -f /var/log/nginx/access.log | لاگ زنده |
sudo tail -F /var/log/nginx/access.log | زنده، حتی بعد از چرخش |
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head | پرتکرارترین IPها |
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head | پرتکرارترین صفحهها |
awk '{print $9}' access.log | sort | uniq -c | sort -rn | توزیع کدهای وضعیت |
awk '$9 == 404 {print $1, $7}' access.log | sort | uniq -c | sort -rn | ۴۰۴ ها با IP |
log_format timed '... rt=$request_time urt=$upstream_response_time'; | قالب با زمان پاسخ (در http) |
access_log /var/log/nginx/shop.access.log timed; | لاگ جدا برای یک سایت |
access_log off; | خاموش کردن لاگ (مثلاً favicon) |
access_log ... if=$loggable; | لاگ شرطی (با map) |
error_log /var/log/nginx/error.log warn; | فقط warn و بالاتر |
sudo nginx -s reopen | باز کردن دوبارهی فایلهای لاگ |
sudo logrotate -d /etc/logrotate.d/nginx | اجرای آزمایشی logrotate |
reverse proxy و HTTPS
reverse proxy
| دستور | کاری که میکند |
|---|---|
proxy_pass http://127.0.0.1:3000; | فرستادن به اپ (مسیر دستنخورده) |
proxy_pass http://127.0.0.1:3000/; | حذف پیشوند location از مسیر |
include proxy_params; | Host، X-Real-IP، X-Forwarded-For، X-Forwarded-Proto |
proxy_set_header X-Real-IP $remote_addr; | IP واقعی کاربر |
proxy_read_timeout 120s; | اپ کند (جلوگیری از ۵۰۴ زودهنگام) |
proxy_connect_timeout 2s; | تشخیص سریع اپ خاموش |
client_max_body_size 20m; | آپلود بزرگتر از ۱ مگابایت |
upstream app { server 127.0.0.1:3000; keepalive 16; } | گروه اپ با اتصالهای باز |
proxy_http_version 1.1; proxy_set_header Connection ""; | لازم برای keepalive |
error_page 502 503 504 /50x.html; | صفحهی دوستانه هنگام قطعی اپ |
ss -tnp | grep :3000 | دیدن اتصال Nginx به اپ |
WebSocket
| دستور | کاری که میکند |
|---|---|
proxy_http_version 1.1; | لازم برای ارتقای پروتکل |
proxy_set_header Upgrade $http_upgrade; | رساندن هدر Upgrade به اپ |
proxy_set_header Connection $connection_upgrade; | upgrade یا close (با map) |
map $http_upgrade $connection_upgrade { default upgrade; '' close; } | در context http (conf.d) |
proxy_read_timeout 1h; | قطع نشدن اتصال ساکت |
curl -i -H 'Connection: Upgrade' -H 'Upgrade: websocket' -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: ...' URL | آزمایش دستدادن (انتظار: 101) |
new WebSocket(`${location.protocol === 'https:' ? 'wss:' : 'ws:'}//${location.host}/ws/`) | آدرس WebSocket نسبی در مرورگر |
sudo apt install python3-websockets | کتابخانهی WebSocket پایتون (برای آزمایش) |
HTTPS با Let's Encrypt
| دستور | کاری که میکند |
|---|---|
sudo apt install certbot python3-certbot-nginx | نصب certbot و افزونهی nginx |
sudo certbot --nginx -d example.com -d www.example.com | گرفتن و نصب گواهی |
sudo certbot --nginx -d example.com --redirect | بهعلاوهی انتقال HTTP به HTTPS |
sudo certbot renew --dry-run | آزمایش تمدید |
sudo certbot certificates | فهرست و تاریخ انقضا |
systemctl list-timers certbot.timer | تمدید خودکار کی اجرا میشود |
listen 443 ssl; ssl_certificate .../fullchain.pem; ssl_certificate_key .../privkey.pem; | TLS دستی در Nginx |
return 301 https://$host$request_uri; | انتقال به HTTPS |
echo | openssl s_client -connect IP:443 -servername example.com | دیدن گواهی و زنجیره |
openssl x509 -in cert.pem -noout -issuer -dates -ext subjectAltName | خواندن گواهی |
openssl req -x509 -newkey rsa:2048 -nodes -days 365 -keyout k.key -out c.crt -subj '/CN=name' | گواهی خودامضا |
امنیت و هدرهای امنیتی
| دستور | کاری که میکند |
|---|---|
server_tokens off; | پنهان کردن نسخه (در http) |
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; | HSTS (روی HTTPS) |
add_header X-Content-Type-Options "nosniff" always; | جلوگیری از حدس نوع فایل |
add_header X-Frame-Options "SAMEORIGIN" always; | جلوگیری از clickjacking |
add_header Referrer-Policy "strict-origin-when-cross-origin" always; | محدود کردن Referer |
add_header Content-Security-Policy-Report-Only "default-src 'self'" always; | آزمایش CSP بدون مسدود کردن |
include snippets/security-headers.conf; | یک بار نوشتن، همهجا استفاده |
proxy_hide_header X-Powered-By; | حذف هدر اپ |
allow 127.0.0.1; deny all; | فقط از IP های مشخص |
htpasswd -c /etc/nginx/.htpasswd admin | ساخت فایل رمز |
auth_basic "Admin"; auth_basic_user_file /etc/nginx/.htpasswd; | رمز برای یک location |
curl -sI https://example.com | دیدن هدرهای پاسخ |
عملکرد و مقیاس
عملکرد: gzip و کش
| دستور | کاری که میکند |
|---|---|
curl -H "Accept-Encoding: gzip" -I URL | فشرده میشود؟ (Content-Encoding) |
curl -so /dev/null -w '%{size_download}' -H 'Accept-Encoding: gzip' URL | اندازهی منتقلشده |
limit_rate 10k; | محدود کردن سرعت هر پاسخ (شبیهسازی اینترنت کند) |
curl -so /dev/null -w "%{time_total}" URL | زمان کل دریافت |
gzip_types text/css application/javascript application/json image/svg+xml; | فشردهسازی CSS و JS و ... |
gzip_comp_level 5; gzip_min_length 256; gzip_vary on; gzip_proxied any; | تنظیم متعادل |
gzip_static on; | سرو .gz آماده |
gzip -k -9 file.css | ساخت file.css.gz و نگه داشتن اصلی |
expires 1y; add_header Cache-Control "public, immutable" always; | فایل hashدار |
add_header Cache-Control "no-cache" always; | HTML: همیشه بپرس |
listen 443 ssl http2; | HTTP/2 (Nginx 1.24) |
load balancing
| دستور | کاری که میکند |
|---|---|
upstream backend { zone backend 64k; server 127.0.0.1:9411; ... } | گروه سرور با حالت مشترک |
proxy_pass http://backend; | فرستادن به گروه |
server 127.0.0.1:9411 weight=3; | سهم بیشتر |
least_conn; | کممشغولترین عضو |
ip_hash; | چسبندگی با سه بخش اول IP |
hash $remote_addr consistent; | چسبندگی با کل IP |
server ... max_fails=2 fail_timeout=10s; | کنار گذاشتن عضو خراب |
server ... backup; | عضو ذخیره |
server ... down; | خارج از سرویس موقت |
log_format lb '... $upstream_addr $upstream_status'; | کدام عضو جواب داد |
systemctl start lx-app@9411 | اجرای نمونه از unit قالبی systemd |
curl --interface 127.0.0.2 URL | درخواست از یک IP دیگر |
resolver 127.0.0.11; server app:80 resolve; | دیدن scale در داکر |
docker compose up -d --scale app=5 | تغییر تعداد نسخهها |
محدودسازی درخواستها
| دستور | کاری که میکند |
|---|---|
limit_req_zone $binary_remote_addr zone=perip:10m rate=2r/s; | تعریف سطل برای هر IP |
limit_req zone=perip; | اعمال بدون هجوم |
limit_req zone=perip burst=5; | صف تا ۵ درخواست |
limit_req zone=perip burst=5 nodelay; | تا ۵ اضافه فوراً |
limit_req_status 429; | کد رد |
limit_req_dry_run on; | فقط لاگ، بدون رد |
limit_req_log_level warn; | سطح لاگ |
limit_conn_zone $binary_remote_addr zone=conns:10m; | تعریف شمارندهی اتصال |
limit_conn conns 2; | حداکثر ۲ همزمان |
geo $limited { default 1; 10.0.0.0/8 0; } | برچسب IP های مورد اعتماد |
map $limited $limit_key { 0 ""; 1 $binary_remote_addr; } | کلید خالی برای لیست سفید |
seq 10 | xargs -P 10 -I{} curl -s -o /dev/null -w "%{http_code}\n" URL | آزمایش با درخواست همزمان |
Nginx در داکر و Compose
| دستور | کاری که میکند |
|---|---|
docker run -d -p 127.0.0.1:8099:80 -v ./conf:/etc/nginx/conf.d:ro nginx:alpine | Nginx با تنظیمات خودت |
docker exec CONTAINER nginx -t | تست تنظیمات |
docker compose exec nginx nginx -s reload | reload بدون ریستارت |
docker compose exec nginx nginx -T | کل تنظیمات نهایی |
docker compose logs nginx | لاگ دسترسی و خطا |
proxy_pass http://api:8080; | proxy به سرویس با اسم |
resolver 127.0.0.11 valid=5s; | DNS داخلی داکر |
server api:8080 resolve; | resolve دوبارهی اسم (در upstream با zone) |
docker compose exec nginx getent hosts api | IP فعلی سرویس |
-v ./templates:/etc/nginx/templates:ro -e NAME=... | قالب با envsubst |
پروژه: استقرار کامل
| دستور | کاری که میکند |
|---|---|
certbot certonly --webroot -w /var/www/letsencrypt -d DOMAIN --deploy-hook "systemctl reload nginx" | گواهی بدون دست زدن به تنظیمات |
ln -sfn RELEASE current.new && mv -T current.new current | عوض کردن اتمی نسخه |
gzip -k -9 assets/* | فایلهای .gz برای gzip_static |
systemctl enable --now lx-shop-api@3001 | نسخهی API از unit قالبی |
listen 443 ssl http2; | HTTPS با HTTP/2 |
return 301 https://shop.test$request_uri; | انتقال به دامنهی اصلی |
include snippets/lx-shop-security.conf; | هدرهای امنیتی در هر location |
proxy_hide_header X-Powered-By; | پنهان کردن فناوری اپ |
location ~ /\. { deny all; } | محافظت از فایلهای نقطهدار |
log_format shop '... rt=$request_time urt=$upstream_response_time'; | لاگ با زمان |
curl -w "%{time_appconnect} %{time_starttransfer}" URL | زمان TLS و اولین بایت |
openssl x509 -in CERT -noout -checkend 1209600 | گواهی تا ۱۴ روز دیگر معتبر است؟ |
certbot renew --dry-run | آزمایش تمدید |
دستوری با این عبارت پیدا نشد.