توی این درس یاد میگیری هر تنظیم Nginx کجا نوشته میشود و چرا آنجا. فایل اصلی nginx.conf را خطبهخط میخوانی؛ دو جزء زبان تنظیمات را میشناسی: directive (یک دستور، مثل listen 80;) و context (یک بلوک آکولادی، مثل server { ... })؛ میبینی تنظیمها چطور از context بیرونی به درونی ارث میرسند. سایتها را به روش Ubuntu در sites-available مینویسی و با sudo ln -s در sites-enabled روشن میکنی، فرقش با conf.d را میفهمی، و هر خطایی را با sudo nginx -t تا شمارهی خط پیدا میکنی؛ بعد با sudo systemctl reload nginx اعمالش میکنی.
مسئله: یک فایل هزار خطی
Section titled “مسئله: یک فایل هزار خطی”روی سروری که پنج سایت دارد، اگر همهی تنظیمات در یک فایل باشند، هر تغییری ترسناک است: یک } اشتباه همهی سایتها را پایین میآورد، نمیدانی هر بلوک مال کدام سایت است، و برای خاموش کردن موقت یک سایت باید چندصد خط را کامنت کنی. Nginx این را با تکهتکه کردن تنظیمات در چند فایل و دستور include حل میکند، و Ubuntu یک قرارداد مرتب برایش دارد: هر سایت یک فایل، و روشن/خاموش کردن با یک لینک.
تشبیه: دفترچهی قوانین یک ساختمان
Section titled “تشبیه: دفترچهی قوانین یک ساختمان”تنظیمات Nginx مثل دفترچهی قوانین یک مجتمع اداری است. یک فصل کلی دارد که برای همه است («ساعت کاری ۸ تا ۱۷»)، بعد برای هر ساختمان (سایت، server) یک فصل، و داخل هر ساختمان برای طبقهها و اتاقها (مسیرها، location) بخشهای جدا. هر قانون کلی برای همهی ساختمانها معتبر است، مگر اینکه فصل یک ساختمان آن را عوض کرده باشد (ارثبری). فصلها هم در پوشههای جدا نگه داشته میشوند و فهرست اصلی میگوید «فصلهای داخل این پوشه را هم بخوان» (include).
اجزای زبان تنظیمات
Section titled “اجزای زبان تنظیمات”directive value; # simple directive: name, values, semicolon
context { # block directive: name, braces directive value; inner_context { directive value; }}- directive ساده: اسم، یک یا چند مقدار، و حتماً
;آخرش. - context (بلوک): اسم و آکولاد؛ directive های داخلش فقط در همان محدوده اثر دارند.
- کامنت: هر چیزی بعد از
#تا آخر خط. - هر directive فقط در context های مشخصی مجاز است (در مستندات هر directive بخش
Context:همین را میگوید).
context های اصلی، از بیرون به درون:
| context | کجاست | چه چیزی را تنظیم میکند |
|---|---|---|
| main (بیرون از همهی بلوکها) | بالای nginx.conf |
کاربر worker ها، تعداد worker، فایل PID، لاگ خطای سراسری |
| events | events { } |
اتصالها: worker_connections |
| http | http { } |
همهچیز مربوط به وب: نوع فایلها، لاگ دسترسی، gzip، و همهی سایتها |
| server | داخل http |
یک سایت (یا یک «میزبان مجازی»): listen، server_name، root |
| location | داخل server |
رفتار یک مسیر (مثل /api/ یا /images/) |
| upstream | داخل http |
گروه سرورهای پشتی (درس load balancing) |
مثالهای عملی
Section titled “مثالهای عملی”این درس روی ماشین آزمایشی server (Ubuntu 24.04، Nginx 1.24 از مخزن Ubuntu) با کاربر root اجرا شده؛ روی سرور خودت جلوی دستورها sudo بگذار (همانطور که در جدولها آمده).
مثال ۱: گشتی در /etc/nginx
Section titled “مثال ۱: گشتی در /etc/nginx”tree -L 1 --noreport /etc/nginxecho "--- سایتهای موجود و فعال:"ls -l /etc/nginx/sites-available/ /etc/nginx/sites-enabled/ | grep -v '^total'/etc/nginx├── conf.d├── fastcgi.conf├── fastcgi_params├── koi-utf├── koi-win├── mime.types├── modules-available├── modules-enabled├── nginx.conf├── proxy_params├── scgi_params├── sites-available├── sites-enabled├── snippets├── uwsgi_params└── win-utf--- سایتهای موجود و فعال:/etc/nginx/sites-available/:-rw-r--r-- 1 root root 2413 Oct 4 12:41 default
/etc/nginx/sites-enabled/:lrwxrwxrwx 1 root root 34 Oct 4 12:41 default -> /etc/nginx/sites-available/defaultدو پوشهی کلیدی: sites-available همهی سایتهایی که تنظیمشان را نوشتهای (فعال یا نه)، و sites-enabled فقط سایتهای روشن؛ که هر کدام فقط یک لینک نمادین (symbolic link) به فایل اصلی است (default -> /etc/nginx/sites-available/default). (درس لینکها در دورهی لینوکس.) conf.d خالی است و snippets چند تکهی آماده دارد.
مثال ۲: خواندن nginx.conf
Section titled “مثال ۲: خواندن nginx.conf”فایل اصلی را بدون کامنتها و خطهای خالی ببینیم:
grep -nvE '^\s*(#|$)' /etc/nginx/nginx.conf1:user www-data;2:worker_processes auto;3:pid /run/nginx.pid;4:error_log /var/log/nginx/error.log;5:include /etc/nginx/modules-enabled/*.conf;7:events {8: worker_connections 768;10:}12:http {18: sendfile on;19: tcp_nopush on;20: types_hash_max_size 2048;26: include /etc/nginx/mime.types;27: default_type application/octet-stream;33: ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE34: ssl_prefer_server_ciphers on;40: access_log /var/log/nginx/access.log;46: gzip on;59: include /etc/nginx/conf.d/*.conf;60: include /etc/nginx/sites-enabled/*;61:}از بالا به پایین:
- main:
user www-data;(کاربر worker ها، درس قبل)،worker_processes auto;،pid /run/nginx.pid;،error_logسراسری، وincludeماژولهای پویا. events { worker_connections 768; }: هر worker حداکثر ۷۶۸ اتصال همزمان.http { ... }: تنظیمهای وب که برای همهی سایتها اعمال میشوند:sendfile on;(فرستادن فایل با کمک مستقیم هسته)،include /etc/nginx/mime.types;(نگاشت پسوند به نوع فایل)،default_typeبرای پسوندهای ناشناخته، تنظیمهای پایهی SSL،access_log،gzip on;.- و دو خط مهم آخر
http:include /etc/nginx/conf.d/*.conf;وinclude /etc/nginx/sites-enabled/*;. یعنی محتوای همهی این فایلها دقیقاً همینجا، داخلhttpقرار میگیرد. برای همین فایلهای سایت باserver { ... }شروع میشوند، نه باhttp.
مثال ۳: یک سایت تازه با sites-available و sudo ln -s
Section titled “مثال ۳: یک سایت تازه با sites-available و sudo ln -s”سایت shop.test را میسازیم. (دامنهی .test برای آزمایش رزرو شده و هیچوقت روی اینترنت واقعی نیست.) اول فایلهای سایت:
mkdir -p /var/www/shop.testecho '<h1>shop.test</h1>' > /var/www/shop.test/index.htmlبعد فایل تنظیمات در sites-available:
server { listen 80; server_name shop.test;
root /var/www/shop.test; index index.html;}تا وقتی لینکش در sites-enabled نباشد، Nginx این فایل را نمیخواند. با ln -s روشنش میکنیم، آزمایش و reload:
ln -s /etc/nginx/sites-available/shop.test /etc/nginx/sites-enabled/ls -l /etc/nginx/sites-enabled/ | grep shopnginx -tsystemctl reload nginxsleep 1curl -s --resolve shop.test:80:127.0.0.1 http://shop.test/lrwxrwxrwx 1 root root 36 Oct 4 12:41 shop.test -> /etc/nginx/sites-available/shop.testnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful<h1>shop.test</h1>ln -s مقصد پوشه/یک لینک با همان اسم درsites-enabledساخت. همیشه مسیر مطلق به فایل اصلی بده؛ لینک نسبی اشتباه، لینک شکسته میسازد (اشتباهات رایج).curl --resolve shop.test:80:127.0.0.1بهcurlمیگوید «shop.testرا127.0.0.1بدان»، بدون اینکه به DNS یا/etc/hostsدست بزنیم. Nginx از هدرHostفهمید درخواست مال کدامserverاست (درس بعد کامل).- بعد از
reloadیکsleep 1گذاشتهایم:systemctl reloadفقط سیگنال را به master میفرستد و برمیگردد؛ ساختن worker های تازه چند لحظه طول میکشد. اگر بلافاصلهcurlبزنی، ممکن است هنوز worker قدیمی (با تنظیمات قبلی) جواب بدهد. در کار روزمره این فاصله را حس نمیکنی، ولی در اسکریپتها مهم است.
خاموش کردن سایت فقط برداشتن لینک است؛ فایل اصلی میماند:
rm /etc/nginx/sites-enabled/shop.testnginx -t 2>&1 | tail -n 1 && systemctl reload nginxsleep 1curl -s --resolve shop.test:80:127.0.0.1 http://shop.test/ | grep -o '<title>.*</title>'ls /etc/nginx/sites-available/ln -s /etc/nginx/sites-available/shop.test /etc/nginx/sites-enabled/systemctl reload nginxnginx: configuration file /etc/nginx/nginx.conf test is successful<title>Welcome to nginx!</title>defaultshop.testبعد از برداشتن لینک، درخواست shop.test به سایت پیشفرض رسید («Welcome to nginx»؛ درس بعد میگوید چرا) و فایل shop.test هنوز در sites-available است. در آخر دوباره روشنش کردیم. (دستور a2ensite که در Apache هست، در Nginx نیست؛ همین ln -s و rm کارش را میکنند.)
مثال ۴: conf.d، فایلهایی که خودشان روشناند
Section titled “مثال ۴: conf.d، فایلهایی که خودشان روشناند”هر فایل *.conf در conf.d خودکار خوانده میشود؛ لینکی لازم نیست. برای خاموش کردن، باید اسمش را عوض کنی (مثلاً .conf.off) یا پاکش کنی:
server { listen 8085; location / { return 200 "status: ok\n"; }}nginx -t 2>&1 | tail -n 1 && systemctl reload nginxsleep 1curl -s http://localhost:8085/mv /etc/nginx/conf.d/status.conf /etc/nginx/conf.d/status.conf.offsystemctl reload nginxsleep 1curl -s -o /dev/null -w "after rename: HTTP %{http_code}\n" http://localhost:8085/ || truemv /etc/nginx/conf.d/status.conf.off /etc/nginx/conf.d/status.confsystemctl reload nginxnginx: configuration file /etc/nginx/nginx.conf test is successfulstatus: okafter rename: HTTP 000return 200 "متن"; یک پاسخ مستقیم بدون هیچ فایلی میدهد (برای صفحهی وضعیت و آزمایش عالی است). بعد از تغییر اسم به .conf.off، الگوی *.conf دیگر آن را نگرفت و پورت ۸۰۸۵ بسته شد (000 یعنی اتصالی برقرار نشد).
کدام را به کار ببری؟ قرارداد رایج: sites-available/sites-enabled برای سایتها (روشن/خاموش با لینک)، و conf.d برای تنظیمهای سراسری http (مثل log_format یا limit_req_zone) و برای ایمیج داکر Nginx که اصلاً sites-* ندارد. هر دو داخل http خوانده میشوند.
مثال ۵: include و snippets برای تکههای تکراری
Section titled “مثال ۵: include و snippets برای تکههای تکراری”تنظیمی که در چند سایت لازم است (مثلاً چند هدر امنیتی)، یک بار در snippets نوشته و هر جا لازم بود include میشود:
add_header X-Content-Type-Options "nosniff" always;add_header X-Frame-Options "SAMEORIGIN" always;sed -i 's|^ index index.html;| index index.html;\n include snippets/lx-headers.conf;|' /etc/nginx/sites-available/shop.testcat /etc/nginx/sites-available/shop.testnginx -t 2>&1 | tail -n 1 && systemctl reload nginxsleep 1curl -s -I --resolve shop.test:80:127.0.0.1 http://shop.test/ | grep -i '^x-'server { listen 80; server_name shop.test;
root /var/www/shop.test; index index.html; include snippets/lx-headers.conf;}nginx: configuration file /etc/nginx/nginx.conf test is successfulX-Content-Type-Options: nosniffX-Frame-Options: SAMEORIGINمسیر نسبی در include (snippets/...) نسبت به پوشهی پیکربندی (/etc/nginx) حساب میشود. حالا اگر سیاست هدرها عوض شود، فقط یک فایل را عوض میکنی. (معنی خود این هدرها در درس امنیت.)
مثال ۶: پیدا کردن خطا با nginx -t
Section titled “مثال ۶: پیدا کردن خطا با nginx -t”nginx -t قبل از هر reload، کل تنظیمات را میخواند و اولین خطا را با اسم فایل و شمارهی خط میگوید. چند خطای رایج را عمداً میسازیم (هر بار روی یک کپی، و بعد برمیگردانیم):
f=/etc/nginx/sites-available/shop.testcp "$f" /root/shop.test.baktry() { echo "=== $1" nginx -t 2>&1 | grep -E 'emerg|warn' | sed -E 's/^[0-9/]+ [0-9:]+ //' cp /root/shop.test.bak "$f"}sed -i 's/server_name shop.test;/server_name shop.test/' "$f"try "1) جا انداختن ;"sed -i 's/root /rooot /' "$f"try "2) اسم directive اشتباه"sed -i 's/^}$//' "$f"try "3) آکولاد بستهنشده"sed -i 's/listen 80;/listen 80;\n worker_connections 100;/' "$f"try "4) directive در context اشتباه"sed -i 's/listen 80;/listen 80;\n listen 80;/' "$f"try "5) listen تکراری"nginx -t 2>&1 | tail -n 1=== 1) جا انداختن ;[warn] 14721#14721: server name "/var/www/shop.test" has suspicious symbols in /etc/nginx/sites-enabled/shop.test:5=== 2) اسم directive اشتباه[emerg] 14726#14726: unknown directive "rooot" in /etc/nginx/sites-enabled/shop.test:5=== 3) آکولاد بستهنشده[emerg] 14731#14731: unexpected end of file, expecting "}" in /etc/nginx/sites-enabled/shop.test:9=== 4) directive در context اشتباه[emerg] 14736#14736: "worker_connections" directive is not allowed here in /etc/nginx/sites-enabled/shop.test:3=== 5) listen تکراری[emerg] 14741#14741: a duplicate listen 0.0.0.0:80 in /etc/nginx/sites-enabled/shop.test:3nginx: configuration file /etc/nginx/nginx.conf test is successfulهر پیام سه چیز دارد: سطح ([emerg] یعنی «اضطراری، شروع نمیکنم»)، توضیح، و in فایل:خط. چند نکته:
- مورد ۱ از همه خطرناکتر است: خطا نداد، فقط یک
[warn]روی خط بعدی! چون Nginx تا;بعدی همه را جزو directive قبلی میداند،server_nameسه مقدار گرفت:shop.test،rootو/var/www/shop.test، و دیگر هیچrootی در سایت نماند (پس پوشهی پیشفرض سرو میشد). هشدار «server name has suspicious symbols» تنها سرنخ بود. پس هشدارها را بخوان، و وقتی خطایی عجیب است، خط قبل را هم نگاه کن. - در ۳، خطا در آخر فایل (
unexpected end of file) گزارش شد؛ آکولاد بستهنشده تا ته فایل کشف نمیشود. - در ۴،
worker_connectionsمال contexteventsاست و درserverمجاز نیست:directive is not allowed here. - در ۵،
listenتکراری در یکserverخطایa duplicate listenداد.
پشت پرده: nginx -T و ارثبری
Section titled “پشت پرده: nginx -T و ارثبری”nginx -T (T بزرگ) کار -t را میکند و بعد کل تنظیمات نهایی را، با محتوای همهی فایلهای includeشده به ترتیب، چاپ میکند. وقتی نمیدانی یک تنظیم از کجا آمده، این ابزار توست:
nginx -T 2>/dev/null | grep '^# configuration file'# configuration file /etc/nginx/nginx.conf:# configuration file /etc/nginx/mime.types:# configuration file /etc/nginx/conf.d/status.conf:# configuration file /etc/nginx/sites-enabled/default:# configuration file /etc/nginx/sites-enabled/shop.test:# configuration file /etc/nginx/snippets/lx-headers.conf:ترتیب: اول nginx.conf، بعد mime.types، بعد conf.d (به ترتیب الفبا)، بعد sites-enabled (به ترتیب الفبا)، و فایلهای snippets هر جا include شدهاند. (ماژولهای پویا هم اگر بودند، همینجا میآمدند.)
ارثبری: directive ای که در context بیرونی نوشته شود، به context های درونی میرسد، مگر اینکه درونی خودش همان directive را داشته باشد. این را با add_header میبینیم که یک استثنای معروف دارد:
add_header X-From-Http "http-level" always;
server { listen 8086; location / { return 200 "no add_header here\n"; } location /own/ { add_header X-From-Location "location-level" always; return 200 "own add_header\n"; }}nginx -t 2>&1 | tail -n 1 && systemctl reload nginxsleep 1echo "=== /"curl -s -i http://localhost:8086/ | grep -i '^x-from'echo "=== /own/"curl -s -i http://localhost:8086/own/ | grep -i '^x-from'rm /etc/nginx/conf.d/lx-inherit.confsystemctl reload nginxnginx: configuration file /etc/nginx/nginx.conf test is successful=== /X-From-Http: http-level=== /own/X-From-Location: location-leveladd_header سطح http (چون فایلهای conf.d داخل http include میشوند) به مسیر / رسید. ولی /own/ که add_header خودش را دارد، هدر سطح http را کاملاً از دست داد. قاعدهی add_header (و چند directive آرایهای دیگر مثل proxy_set_header): اگر سطح درونی حتی یک add_header داشته باشد، هیچکدام از سطح بیرونی به ارث نمیرسد. این دلیل خیلی از «چرا هدر امنیتیام روی بعضی صفحهها نیست؟»هاست؛ راهحل رایج همان include snippets/... در هر سطحی است که add_header دارد.
جدولهای مرجع
Section titled “جدولهای مرجع”فایلها و پوشهها (Ubuntu):
| مسیر | محتوا | کی خوانده میشود |
|---|---|---|
/etc/nginx/nginx.conf |
فایل اصلی | همیشه |
/etc/nginx/conf.d/*.conf |
تنظیمهای اضافه | خودکار، داخل http |
/etc/nginx/sites-available/ |
همهی سایتها | هیچوقت مستقیم |
/etc/nginx/sites-enabled/ |
لینک سایتهای فعال | داخل http، همهی فایلها |
/etc/nginx/snippets/ |
تکههای قابل استفادهی دوباره | فقط با include |
/etc/nginx/mime.types |
پسوند ← Content-Type |
با include در http |
دستورهای این درس:
| دستور | کار |
|---|---|
sudo nginx -t |
آزمایش تنظیمات (نحو، فایلها، پورتها) |
sudo nginx -T |
آزمایش + چاپ کل تنظیمات نهایی |
sudo systemctl reload nginx |
اعمال بدون قطع |
sudo ln -s /etc/nginx/sites-available/SITE /etc/nginx/sites-enabled/ |
روشن کردن سایت |
sudo rm /etc/nginx/sites-enabled/SITE |
خاموش کردن سایت (فایل اصلی میماند) |
sudo nginx -t && sudo systemctl reload nginx |
الگوی امن بعد از هر تغییر |
سطح پیامهای Nginx (از کماهمیت به مهم): debug، info، notice، warn، error، crit، alert، emerg.
اشتباهات رایج
Section titled “اشتباهات رایج”۱) نوشتن فایل در sites-available و فراموش کردن لینک
Section titled “۱) نوشتن فایل در sites-available و فراموش کردن لینک”فایل را نوشتی، reload کردی و هیچ تغییری نمیبینی. راهحل: ls -l /etc/nginx/sites-enabled/؛ اگر لینک نیست، sudo ln -s ....
۲) لینک نسبی شکسته
Section titled “۲) لینک نسبی شکسته”cd /etc/nginx/sites-availableln -s blog.test ../sites-enabled/blog.testls -l ../sites-enabled/blog.testnginx -t 2>&1 | grep -E 'emerg' | sed -E 's/^[0-9/]+ [0-9:]+ //'rm ../sites-enabled/blog.testcd ~lrwxrwxrwx 1 root root 9 Oct 4 12:41 ../sites-enabled/blog.test -> blog.test[emerg] 14776#14776: open() "/etc/nginx/sites-enabled/blog.test" failed (40: Too many levels of symbolic links) in /etc/nginx/nginx.conf:60لینک نسبی نسبت به پوشهی خود لینک حل میشود، نه پوشهای که در آن بودی؛ پس sites-enabled/blog.test به blog.test در همان sites-enabled، یعنی به خودش، اشاره کرد و Nginx با Too many levels of symbolic links (حلقهی لینک) شکست خورد. راهحل: همیشه مسیر مطلق: sudo ln -s /etc/nginx/sites-available/blog.test /etc/nginx/sites-enabled/.
۳) کپی کردن بهجای لینک
Section titled “۳) کپی کردن بهجای لینک”اگر بهجای لینک فایل را کپی کنی، دو نسخه داری؛ بعداً sites-available را ویرایش میکنی و هیچ اثری نمیبینی چون Nginx نسخهی کپی را میخواند. راهحل: ls -l باید -> نشان دهد.
۴) فایل پشتیبان در sites-enabled
Section titled “۴) فایل پشتیبان در sites-enabled”cp /etc/nginx/sites-available/shop.test /etc/nginx/sites-enabled/shop.test.baknginx -t 2>&1 | grep -E 'warn|emerg' | sed -E 's/^[0-9/]+ [0-9:]+ //'rm /etc/nginx/sites-enabled/shop.test.bak[warn] 14781#14781: conflicting server name "shop.test" on 0.0.0.0:80, ignoredinclude sites-enabled/* همهی فایلها را میخواند، حتی .bak و ~؛ حالا دو server با یک اسم داری و هشدار conflicting server name میگیری (و یکی نادیده گرفته میشود). راهحل: پشتیبان را جای دیگری بگذار (مثلاً /root/)، نه در sites-enabled یا conf.d.
۵) reload بدون -t
Section titled “۵) reload بدون -t”درس قبل: با تنظیم خراب، reload شکست میخورد (و تو فکر میکنی تغییرت اعمال شده). راهحل: sudo nginx -t && sudo systemctl reload nginx.
۶) گم شدن add_header ها با ارثبری
Section titled “۶) گم شدن add_header ها با ارثبری”پشت پرده: یک add_header در location همهی add_header های بیرونی را برای آن مسیر حذف میکند. راهحل: هدرهای مشترک را در یک snippet بگذار و در هر سطحی که add_header دارد include کن.
تمرین اصلی درس: در فایل سایت shop.test یک خطای عمدی بساز (مثلاً ; آخر root را پاک کن)، با nginx -t آن را پیدا کن (پیام و شمارهی خط را بخوان)، درستش کن و ثابت کن nginx -t دوباره موفق است. در این فاصله سایت باید بالا بماند (چون reload نکردهای).
دیدن جواب
f=/etc/nginx/sites-available/shop.testsed -i 's|root /var/www/shop.test;|root /var/www/shop.test|' "$f"grep -n 'root' "$f"nginx -techo "--- سایت در این فاصله: $(curl -s --resolve shop.test:80:127.0.0.1 http://shop.test/)"sed -i 's|root /var/www/shop.test$|root /var/www/shop.test;|' "$f"nginx -t5: root /var/www/shop.test2026/10/04 12:41:47 [emerg] 14787#14787: invalid number of arguments in "root" directive in /etc/nginx/sites-enabled/shop.test:6nginx: configuration file /etc/nginx/nginx.conf test failed--- سایت در این فاصله: <h1>shop.test</h1>nginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successfulپیام به خط بعد از root اشاره کرد (index را جزو مقدارهای root دید و بهخاطر تعداد مقدار غلط خطا داد). تا وقتی reload نکنی، Nginx با تنظیمات قبلی کار میکند؛ برای همین سایت در تمام این مدت بالا بود.
سایت دوم blog.test را با فایل جدا در sites-available بساز (پوشهی /var/www/blog.test با یک index.html)، روشنش کن و با curl --resolve نشان بده هر دو سایت (shop.test و blog.test) روی یک پورت جواب درست میدهند. بعد blog.test را خاموش کن، بدون اینکه فایلش پاک شود.
دیدن جواب
mkdir -p /var/www/blog.testecho '<h1>blog.test</h1>' > /var/www/blog.test/index.htmlcat > /etc/nginx/sites-available/blog.test <<'EOF'server { listen 80; server_name blog.test; root /var/www/blog.test; index index.html;}EOFln -s /etc/nginx/sites-available/blog.test /etc/nginx/sites-enabled/nginx -t 2>&1 | tail -n 1 && systemctl reload nginxsleep 1for h in shop.test blog.test; do printf '%-10s -> ' "$h" curl -s --resolve "$h:80:127.0.0.1" "http://$h/"donerm /etc/nginx/sites-enabled/blog.testsystemctl reload nginxsleep 1echo "--- بعد از خاموش کردن blog.test:"curl -s --resolve blog.test:80:127.0.0.1 http://blog.test/ | grep -o '<title>.*</title>'ls /etc/nginx/sites-available/ /etc/nginx/sites-enabled/nginx: configuration file /etc/nginx/nginx.conf test is successfulshop.test -> <h1>shop.test</h1>blog.test -> <h1>blog.test</h1>--- بعد از خاموش کردن blog.test:<title>Welcome to nginx!</title>/etc/nginx/sites-available/:blog.testdefaultshop.test
/etc/nginx/sites-enabled/:defaultshop.testدو سایت روی یک پورت ۸۰، و Nginx با server_name (از هدر Host) بینشان فرق گذاشت. بعد از برداشتن لینک، blog.test به سایت پیشفرض رسید، ولی فایلش در sites-available ماند و با یک ln -s برمیگردد.
با nginx -T یک اسکریپت کوچک بنویس که برای هر فایل تنظیماتی که Nginx واقعاً میخواند، تعداد بلوکهای server و location و فهرست پورتهای listen را گزارش کند. (راهنمایی: خروجی nginx -T هر فایل را با خط # configuration file PATH: شروع میکند؛ با awk آن را تکه کن.)
دیدن جواب
nginx -T 2>/dev/null | awk ' /^# configuration file / { file = $4; sub(/:$/, "", file); order[++n] = file; next } { line = $0 sub(/#.*/, "", line) if (line ~ /^[ \t]*server[ \t]*\{/) servers[file]++ if (line ~ /^[ \t]*location[ \t]/) locations[file]++ if (line ~ /^[ \t]*listen[ \t]/) { sub(/^[ \t]*listen[ \t]+/, "", line); sub(/;.*/, "", line); ports[file] = ports[file] " " line } } END { for (i = 1; i <= n; i++) { f = order[i] if (servers[f] + locations[f] == 0) continue printf "%-42s server=%d location=%d listen:%s\n", f, servers[f], locations[f], ports[f] } }'/etc/nginx/conf.d/status.conf server=1 location=1 listen: 8085/etc/nginx/sites-enabled/default server=1 location=1 listen: 80 default_server/etc/nginx/sites-enabled/shop.test server=1 location=0 listen: 80awk هر بار که به خط # configuration file میرسد، اسم فایل فعلی را عوض میکند و بقیهی خطها را به حساب همان فایل میگذارد. کامنتها را اول با sub(/#.*/, "", line) برمیداریم تا خطهای کامنتشده (مثل listen [::]:80 در default) شمرده نشوند. خروجی تصویر کوچکی از کل سرور میدهد: کدام فایل چند سایت و مسیر دارد و روی کدام پورتها گوش میدهد.
آزمونک
Section titled “آزمونک”فایل تنظیمات سایتی در sites-enabled با کدام بلوک شروع میشود و چرا؟
include /etc/nginx/sites-enabled/*; داخل http { } نوشته شده؛ محتوای فایل دقیقاً همانجا قرار میگیرد.
فرق sites-available و sites-enabled چیست؟
روشن/خاموش با ln -s و rm.
nginx -t پیام «unexpected "index" in /etc/nginx/sites-enabled/shop:6» میدهد ولی خط ۶ درست است. اول کجا را نگاه میکنی؟
Nginx تا ; بعدی همه را جزو directive قبلی میداند.
پیام «"worker_connections" directive is not allowed here» یعنی چه؟
بخش Context در مستندات هر directive.
در http هدر X-A را با add_header گذاشتهای و در یک location فقط X-B را. درخواست به آن location کدام هدرها را دارد؟
هدرهای مشترک را در snippet بگذار و include کن.
فایل shop.conf.bak را در sites-enabled کپی کردهای. چه میشود؟
پشتیبان را بیرون از sites-enabled و conf.d نگه دار.
میخواهی ببینی یک تنظیم از کدام فایل آمده و تنظیمات نهایی بعد از همهی include ها چیست. کدام دستور؟
nginx -T همهی فایلها را به ترتیب خواندن، با خط # configuration file چاپ میکند.
جمعبندی
Section titled “جمعبندی”- زبان تنظیمات دو جزء دارد: directive (
name value;، با;اجباری) و context (name { ... }). context های اصلی: main ←eventsوhttp←server←location. هر directive فقط در context های مشخصی مجاز است. nginx.confدر Ubuntu داخلhttpاینها راincludeمیکند:conf.d/*.conf(خودکار) وsites-enabled/*(لینکها). پس فایل سایت باserverشروع میشود.- روشن کردن سایت: فایل در
sites-availableوsudo ln -s /etc/nginx/sites-available/SITE /etc/nginx/sites-enabled/(مسیر مطلق). خاموش:rmلینک. conf.dبرای تنظیمهای سراسریhttpو ایمیج داکر؛snippets+includeبرای تکههای تکراری.- ارثبری: تنظیم بیرونی به درونی میرسد مگر درونی خودش داشته باشد؛
add_headerدر سطح درونی همهی بیرونیها را حذف میکند. sudo nginx -tخطا را با فایل و شمارهی خط میگوید (خط قبل را هم ببین)؛nginx -Tتنظیمات نهایی را چاپ میکند؛ بعدsudo systemctl reload nginx.
| دستور | کاری که میکند |
|---|---|
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 | خواندن فایل بدون کامنت |