رفتن به محتوا
LoopX

آزمون بخش ۱: مبانی Nginx

این آزمون هفت درس بخش «مبانی» را می‌سنجد: از Nginx چیست؟ تا لاگ‌ها. جواب هر سؤال همان لحظه با توضیح نشان داده می‌شود و نتیجه‌ات در همین مرورگر ذخیره می‌شود (پیشرفت من).

؟ آزمون بخش ۱
  1. اپ Python تو روی 127.0.0.1:8000 اجرا می‌شود و می‌خواهی کاربران از پورت ۸۰ به آن برسند. Nginx در این حالت چه نقشی دارد؟

  2. چرا worker های Nginx با کاربر www-data اجرا می‌شوند و نه root؟

  3. apt install nginx با «Errors were encountered while processing: nginx» تمام شد. اولین کار؟

  4. تنظیمات را عوض کرده‌ای و یک ; جا انداخته‌ای. کدام دستور سایت را از دسترس خارج می‌کند؟

  5. بعد از چند start و restart پشت سر هم، systemctl start nginx پیام «Start request repeated too quickly» می‌دهد. چه می‌کنی؟

  6. یک فایل سایت در /etc/nginx/sites-available نوشته‌ای، nginx -t و reload موفق بودند ولی هیچ تغییری نمی‌بینی. محتمل‌ترین علت؟

  7. nginx -t فقط یک [warn] می‌دهد: server name "/var/www/shop" has suspicious symbols. محتمل‌ترین علت؟

  8. در http یک add_header گذاشته‌ای و در یک location یک add_header دیگر. پاسخ آن location کدام هدرها را دارد؟

  9. کسی IP سرور را مستقیم در مرورگر زده و پنل وبلاگ را دیده؛ هیچ server block ای default_server ندارد. چرا؟

  10. server_name *.shop.test با کدام جور نمی‌شود؟

  11. می‌خواهی www.shop.test با حفظ مسیر و query string به shop.test برود. کدام؟

  12. هم location /images/ هست و هم location ~* \.png$. درخواست /images/a.png به کدام می‌رسد؟

  13. دو regex داری که هر دو با /admin/app.js جور می‌شوند. کدام برنده است؟

  14. location /files { alias /srv/files/; } چه مشکلی دارد؟

  15. در location /static/ { root /srv/web; } درخواست /static/app.css کدام فایل را می‌خواند؟

  16. در یک SPA، رفرش روی /dashboard ۴۰۴ می‌دهد. تنظیم درست location / چیست؟

  17. صفحه‌ی ۴۰۴ سفارشی را در آخر try_files گذاشته‌ای (try_files $uri /404.html). مشکل؟

  18. root سایت روی پوشه‌ی پروژه (با .git و .env) است. بهترین کار؟

  19. کدام دستور ده IP پرتکرار را از access.log (قالب combined) درمی‌آورد؟

  20. می‌خواهی زمان پاسخ هر درخواست و سهم اپ پشتی را در لاگ ببینی. چه می‌کنی؟

  21. لاگ را با mv چرخاندی و Nginx هنوز در فایل .1 می‌نویسد. راه‌حل؟

  22. tail -f access.log بعد از چرخش شبانه‌ی logrotate چیزی نشان نمی‌دهد. چه بزنی؟

🏁 چالش: یک سرور، دو سایت، کاملاً درستسخت

روی یک سرور (یا ماشین آزمایشی) این‌ها را با Nginx بساز و با یک اسکریپت آزمایش ثابت کن همه درست‌اند:

۱. catch-all: هر دامنه‌ی ناشناخته (یا IP خالی) اتصالش بسته شود (444). ۲. docs.test: یک سایت چندصفحه‌ای؛ آدرس‌های بدون .html کار کنند (/guide ← guide.html)، صفحه‌ی ۴۰۴ سفارشی با کد ۴۰۴، و فایل‌های مخفی (.env) بسته باشند. ۳. app.test: یک SPA؛ هر مسیر صفحه به index.html برسد ولی /assets/ گمشده ۴۰۴ واقعی بدهد؛ و www.app.test با 301 به app.test (با حفظ مسیر) برود. ۴. لاگ: هر سایت access log جدای خودش را داشته باشد. ۵. اسکریپت آزمایش برای هر قانون یک درخواست بفرستد و PASS یا FAIL چاپ کند.

راهنمایی

دامنه‌ها را در /etc/hosts به 127.0.0.1 بفرست. برای catch-all listen 80 default_server; server_name _; return 444; (و سایت پیش‌فرض Ubuntu را خاموش کن). برای docs.test: try_files $uri $uri.html $uri/ =404; و error_page 404 /404.html; و location ~ /\.(?!well-known) { deny all; }. برای app.test: location /assets/ { try_files $uri =404; } و location / { try_files $uri $uri/ /index.html; }. در اسکریپت، یک تابع check URL کد-مورد-انتظار بنویس که با curl -s -o /dev/null -w '%{http_code}' کد را بگیرد (برای 444، curl کد 000 می‌دهد).

راه‌حل
Terminal window
export LXC=/root/challenge
rm -rf "$LXC" && mkdir -p "$LXC"
rm -f /etc/nginx/sites-enabled/*
grep -v '\.test$' /etc/hosts > /tmp/hosts.lx; cat /tmp/hosts.lx > /etc/hosts
echo '127.0.0.1 docs.test app.test www.app.test' >> /etc/hosts
mkdir -p /var/www/docs.test /var/www/app.test/assets
echo '<h1>Docs home</h1>' > /var/www/docs.test/index.html
echo '<h1>Guide</h1>' > /var/www/docs.test/guide.html
echo '<h1>Not found (docs)</h1>' > /var/www/docs.test/404.html
echo 'SECRET=1' > /var/www/docs.test/.env
echo '<!doctype html><div id="app">SPA</div><script src="/assets/app.js"></script>' > /var/www/app.test/index.html
echo 'console.log("app")' > /var/www/app.test/assets/app.js
cat > /etc/nginx/sites-available/00-catchall <<'EOF'
server {
listen 80 default_server;
server_name _;
return 444;
}
EOF
cat > /etc/nginx/sites-available/docs.test <<'EOF'
server {
listen 80;
server_name docs.test;
root /var/www/docs.test;
index index.html;
access_log /var/log/nginx/docs.access.log;
location ~ /\.(?!well-known) {
deny all;
}
location / {
try_files $uri $uri.html $uri/ =404;
}
error_page 404 /404.html;
}
EOF
cat > /etc/nginx/sites-available/app.test <<'EOF'
server {
listen 80;
server_name www.app.test;
return 301 http://app.test$request_uri;
}
server {
listen 80;
server_name app.test;
root /var/www/app.test;
index index.html;
access_log /var/log/nginx/app.access.log;
location /assets/ {
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.html;
}
}
EOF
for s in 00-catchall docs.test app.test; do ln -s /etc/nginx/sites-available/$s /etc/nginx/sites-enabled/; done
nginx -t 2>&1 | tail -n 1 && systemctl reload nginx
sleep 1
cat > "$LXC/check.sh" <<'EOF'
#!/usr/bin/env bash
# check.sh: one request per rule, PASS/FAIL
pass=0 fail=0
check() {
local url=$1 want=$2 got
got=$(curl -s -o /dev/null -w '%{http_code}' "$url")
if [[ $got == "$want" ]]; then
echo "PASS $want $url"; pass=$((pass + 1))
else
echo "FAIL want $want got $got $url"; fail=$((fail + 1))
fi
}
check http://127.0.0.1/ 000
check http://unknown.test/ 000
check http://docs.test/ 200
check http://docs.test/guide 200
check http://docs.test/nothing 404
check http://docs.test/.env 403
check http://app.test/settings/profile 200
check http://app.test/assets/app.js 200
check http://app.test/assets/old.js 404
check 'http://www.app.test/a?b=1' 301
echo "redirect target: $(curl -s -o /dev/null -w '%{redirect_url}' 'http://www.app.test/a?b=1')"
echo "custom 404 body: $(curl -s http://docs.test/nothing)"
echo "docs log lines: $(wc -l < /var/log/nginx/docs.access.log), app log lines: $(wc -l < /var/log/nginx/app.access.log)"
echo "result: $pass passed, $fail failed"
(( fail == 0 ))
EOF
chmod +x "$LXC/check.sh"
"$LXC/check.sh"
خروجی
nginx: configuration file /etc/nginx/nginx.conf test is successful
PASS 000 http://127.0.0.1/
PASS 000 http://unknown.test/
PASS 200 http://docs.test/
PASS 200 http://docs.test/guide
PASS 404 http://docs.test/nothing
PASS 403 http://docs.test/.env
PASS 200 http://app.test/settings/profile
PASS 200 http://app.test/assets/app.js
PASS 404 http://app.test/assets/old.js
PASS 301 http://www.app.test/a?b=1
redirect target: http://app.test/a?b=1
custom 404 body: <h1>Not found (docs)</h1>
docs log lines: 5, app log lines: 3
result: 10 passed, 0 failed

unknown.test در /etc/hosts نیست، پس curl اصلاً به سرور نرسید و کد 000 داد؛ برای آزمایش واقعی catch-all، درخواست مستقیم به IP (127.0.0.1) هم هست که به سرور می‌رسد و با 444 بسته می‌شود (باز هم 000، چون پاسخی نیامد). همه‌ی قانون‌ها با یک درخواست ثابت شدند و هر سایت لاگ خودش را دارد.