Nginx Configuration برای وردپرس (WordPress) یکی از بنیادی‌ترین و در عین حال کم‌شناخته‌شده‌ترین لایه‌های بهینه‌سازی یک سایت حرفه‌ای است. Nginx به‌عنوان یک وب‌سرور غیرهمزمان و مبتنی بر رویداد (Event-Driven)، برای سایت‌های پربازدید و پرمصرف، عملکرد بسیار بهتری نسبت به Apache ارائه می‌دهد؛ به‌شرط آنکه پیکربندی آن به‌درستی انجام شود. یک پیکربندی نادرست Nginx می‌تواند از یک سو منجر به خطاهای ۵۰۲ و ۵۰۴ شود، و از سوی دیگر بخش بزرگی از توانایی‌های واقعی این سرور را بی‌استفاده بگذارد. در مقابل، یک پیکربندی دقیق می‌تواند زمان پاسخ سرور (TTFB) را چند برابر کاهش دهد، مصرف حافظه را به‌شدت پایین بیاورد، محافظت لایه‌ای در برابر حملات را فراهم کند، و تجربه کاربری را در سایت‌های فروشگاهی و پرترافیک متحول کند. در این نوشتار، معماری درخواست در Nginx، تفاوت‌های کلیدی با Apache، پیکربندی اصولی برای وردپرس، بهینه‌سازی FastCGI و PHP-FPM، قوانین امنیتی، لایه‌بندی کش، تنظیمات ووکامرس، و نکات پیشرفته برای مهندسان ارشد بررسی می‌شود.

در دهه‌ای که با سایت‌های وردپرسی در مقیاس‌های مختلف کار کرده‌ام، یکی از پرتکرارترین موضوعاتی که در بهبود عملکرد به آن رسیده‌ام، پیکربندی Nginx است. تجربه‌ام نشان داده که بسیاری از سایتی که روی Apache کند بودند، با مهاجرت به Nginx و پیکربندی دقیق، سرعتشان چند برابر شده، بی‌آنکه سخت‌افزار تغییر کند. آنچه در ادامه می‌آید، چارچوبی عملی و آزموده‌شده است که از پیکربندی پایه تا تنظیمات پیشرفته برای بارهای سنگین را پوشش می‌دهد. تمرکز بر مواردی است که در پروژه‌های واقعی بیشترین تأثیر را داشته‌اند.

Nginx چیست و چرا برای وردپرس انتخاب بهتری است؟

Nginx (تلفظ «اِنجین-اِکس») یک وب‌سرور متن‌باز است که در سال ۲۰۰۴ توسط ایگور سیسوئف با تمرکز بر مقیاس‌پذیری و عملکرد بالا طراحی شد. این سرور از همان ابتدا برای حل مشکل C10K (پردازش ۱۰٫۰۰۰ اتصال همزمان) طراحی شد؛ مشکلی که Apache در آن زمان با مدل process-per-request خود نمی‌توانست به‌خوبی حل کند.

Nginx در چند سال گذشته به یکی از محبوب‌ترین وب‌سرورهای جهان تبدیل شده و در سایت‌های پربازدید مانند Netflix، Cloudflare، Dropbox و WordPress.com استفاده می‌شود. برای مطالعه بیشتر درباره مفهوم وب‌سرور و نقش آن، می‌توانید به منبع عمومی Nginx مراجعه کنید.

دلایل اصلی انتخاب Nginx برای سایت‌های وردپرسی:

  • معماری غیرهمزمان: Nginx با یک حلقه رویداد (Event Loop) واحد، هزاران اتصال همزمان را با مصرف حافظه کم مدیریت می‌کند.
  • مصرف حافظه پایین: در مقایسه با Apache، Nginx در بارهای سنگین حافظه کمتری مصرف می‌کند.
  • پردازش فایل‌های استاتیک: Nginx برای سرو فایل‌های استاتیک (تصاویر، CSS، JavaScript) بسیار بهینه است.
  • Reverse Proxy قوی: Nginx می‌تواند به‌عنوان پروکسی معکوس برای Apache، Node.js یا PHP-FPM عمل کند.
  • پیکربندی انعطاف‌پذیر: فایل پیکربندی Nginx از قدرت بالایی برای سفارشی‌سازی برخوردار است.
  • کش داخلی: Nginx از FastCGI Cache پشتیبانی می‌کند که می‌تواند بار دیتابیس و PHP را به‌شدت کاهش دهد.
  • امنیت: Nginx به‌طور پیش‌فرض بخش بزرگی از حملات رایج را دفع می‌کند.

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

Nginx یک وب‌سرور نیست، یک معماری است. تفاوت آن با Apache فقط در سرعت نیست، در نحوه تفکر درباره همزمانی و منابع است.

تفاوت معماری Nginx و Apache

درک تفاوت‌های بنیادین Nginx و Apache، پیش‌نیاز تصمیم‌گیری درست درباره معماری سرور است.

مدل پردازش درخواست

Apache به‌طور سنتی از مدل‌های MPM (Multi-Processing Module) استفاده می‌کند که هر اتصال را به یک thread یا process اختصاص می‌دهد:

  • prefork: هر درخواست در یک process جداگانه. مصرف حافظه بالا.
  • worker: ترکیبی از process و thread. بهینه‌تر از prefork.
  • event: مدل بهینه‌تر Apache که از Keep-Alive پشتیبانی می‌کند.

Nginx از یک مدل کاملاً متفاوت استفاده می‌کند: یک master process و چند worker process که هرکدام یک event loop دارند. هر worker می‌تواند هزاران اتصال را به‌طور همزمان مدیریت کند، بدون آنکه برای هر اتصال، thread یا process جداگانه‌ای بسازد.

ویژگیApacheNginx
مدل پردازشProcess/Thread per requestEvent-driven
مصرف حافظهبالا در همزمانی بالاپایین و پایدار
همزمانی (C10K)محدودعالی
فایل‌های استاتیکخوبعالی
پیکربندیhtaccess و httpd.confفقط فایل‌های سراسری
ماژول‌های داینامیکبلهمحدود

جایگاه htaccess در برابر فایل پیکربندی

یکی از تفاوت‌های کلیدی، عدم پشتیبانی Nginx از فایل .htaccess است. در Apache، فایل .htaccess در هر پوشه می‌تواند قوانین تعریف کند و در هر درخواست بارگذاری می‌شود. این رویکرد، انعطاف‌پذیری بالایی فراهم می‌کند، اما هزینه‌ای نیز دارد: هر درخواست نیازمند بررسی فایل‌های .htaccess در مسیر است.

Nginx به‌جای .htaccess، از یک فایل پیکربندی مرکزی استفاده می‌کند. این رویکرد، عملکرد بهتری دارد، اما تغییر قوانین نیازمند دسترسی به فایل پیکربندی و ریلود Nginx است. بسیاری از افزونه‌های وردپرس که قوانین rewrite یا امنیتی خود را در .htaccess می‌نویسند، در Nginx کار نمی‌کنند و باید قوانین معادل به‌صورت دستی اضافه شوند.

برای مشاهده نمونه این تفاوت، مقاله انتقال HTTP به HTTPS با کد htaccess نمونه‌ای از رویکرد Apache است که در Nginx باید به‌صورت دیگری نوشته شود.

مقایسه عملکرد در سناریوهای واقعی

در آزمون‌های عملی روی سایت‌های وردپرسی با ترافیک متوسط (۱۰۰ هزار بازدید ماهانه)، نتایج زیر مشاهده شده:

  • سرو فایل‌های استاتیک: Nginx تا ۳ برابر سریع‌تر از Apache پیش‌فرض.
  • پردازش PHP: تفاوت کم، در صورتی که هر دو از PHP-FPM استفاده کنند.
  • مصرف حافظه در بار بالا: Nginx تا ۴۰٪ کمتر از Apache.
  • زمان پاسخ در همزمانی بالا: Nginx پایدارتر، Apache با نوسان بیشتر.

در سایت‌های پربازدید یا فروشگاهی، این تفاوت‌ها می‌توانند مستقیماً بر نرخ تبدیل اثر بگذارند. برای مطالعه بیشتر درباره تأثیر سرعت بر فروش، مقاله افزایش سرعت فروشگاه ووکامرس را ببینید.

جریان پردازش درخواست در Nginx

درک جریان پردازش درخواست، برای پیکربندی دقیق ضروری است.

Master Process و Worker Process

Nginx از یک معماری دو‌سطحی استفاده می‌کند:

  • Master Process: مسئول خواندن فایل پیکربندی، مدیریت workerها و مدیریت سیگنال‌ها.
  • Worker Process: مسئول پردازش درخواست‌های واقعی. هر worker یک event loop دارد.
user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
}

تنظیم worker_processes auto باعث می‌شود Nginx به‌طور خودکار تعداد workerها را بر اساس تعداد هسته‌های CPU تنظیم کند. در سرورهایی با ۴ یا ۸ هسته، این تنظیم به عملکرد بهینه منجر می‌شود.

Event Loop و مقیاس‌پذیری

هر worker process دارای یک event loop است که با استفاده از مکانیزم‌های سیستمی مانند epoll در لینوکس، هزاران اتصال را به‌طور همزمان مدیریت می‌کند. برخلاف Apache که برای هر اتصال یک thread یا process اختصاص می‌دهد، Nginx از یک مدل غیرهمزمان استفاده می‌کند که به آن اجازه می‌دهد با منابع محدود، تعداد بسیار بالایی اتصال را پشتیبانی کند.

تنظیم worker_connections تعیین می‌کند هر worker چند اتصال همزمان را می‌تواند مدیریت کند. مقدار پیش‌فرض ۷۶۸ است، اما برای سایت‌های پربازدید، مقادیر ۲۰۴۸ تا ۸۱۹۲ توصیه می‌شود. حداکثر اتصال همزمان سرور برابر است با: worker_processes × worker_connections.

Location Matching و اولویت بلوک‌ها

یکی از مفاهیم کلیدی در پیکربندی Nginx، بلوک‌های location هستند که تعیین می‌کنند کدام درخواست‌ها با کدام قوانین پردازش شوند. اولویت بلوک‌ها به ترتیب زیر است:

  1. location = /path: تطابق دقیق (Exact Match). بالاترین اولویت.
  2. location ^~ /path: تطابق پیشوندی با اولویت بالا.
  3. location ~ pattern: تطابق regex (حساس به حروف بزرگ و کوچک).
  4. location ~* pattern: تطابق regex (غیرحساس به حروف بزرگ و کوچک).
  5. location /path: تطابق پیشوندی عادی. کمترین اولویت.

این اولویت‌بندی، دلیل بسیاری از خطاهای پیکربندی است. برای مثال، اگر یک بلوک location / با یک بلوک location ~ \.php$ داشته باشید، درخواست‌های PHP با بلوک دوم پردازش می‌شوند، زیرا اولویت regex بالاتر است.

پیکربندی پایه Nginx برای وردپرس

یک پیکربندی پایه و درست، پایه تمام بهینه‌سازی‌های بعدی است.

بلوک server و تعریف دامنه

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    root /var/www/html;
    index index.php index.html index.htm;
    
    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # Logs
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;
}

این ساختار دو‌سطحی، ابتدا درخواست‌های HTTP را به HTTPS ریدایرکت می‌کند و سپس درخواست‌های HTTPS را پردازش می‌کند. برای آشنایی با نصب و پیکربندی SSL، مقاله چگونه SSL سایت را نصب و فعال کنیم؟ را ببینید.

root و index

تنظیم root مسیر ریشه فایل‌های سایت را مشخص می‌کند و index فایل‌های پیش‌فرض برای پوشه‌ها را تعیین می‌کند. در وردپرس، ترتیب زیر توصیه می‌شود:

index index.php index.html index.htm;

قرار دادن index.php در ابتدا، تضمین می‌کند که فایل PHP وردپرس به‌جای فایل‌های HTML ثابت اجرا شود.

پردازش فایل‌های PHP

پردازش فایل‌های PHP در Nginx از طریق FastCGI و PHP-FPM انجام می‌شود:

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
}

نکات کلیدی:

  • try_files $uri =404: جلوگیری از حمله اجرای فایل‌های ناموجود.
  • fastcgi_split_path_info: جدا کردن مسیر PHP از پارامترهای اضافی.
  • fastcgi_pass: آدرس PHP-FPM، می‌تواند سوکت یونیکس یا TCP باشد.
  • SCRIPT_FILENAME: مسیر کامل فایل PHP که باید اجرا شود.

استفاده از سوکت یونیکس (Unix Socket) به‌جای TCP، عملکرد بهتری دارد، زیرا از سربار شبکه محلی جلوگیری می‌کند. برای مطالعه بیشتر درباره PHP، مقاله PHP Version و سازگاری وردپرس را ببینید.

try_files و مدیریت Permalink

وردپرس از ساختار Permalink استفاده می‌کند که در آن، URLها به‌صورت مسیرهای مجازی نمایش داده می‌شوند. در Apache، این کار با فایل .htaccess و دستور RewriteRule انجام می‌شود. در Nginx، این کار با بلوک try_files انجام می‌شود:

location / {
    try_files $uri $uri/ /index.php?$args;
}

این بلوک به Nginx می‌گوید: ابتدا فایل درخواستی را جستجو کن، سپس پوشه، و در نهایت درخواست را به index.php ارسال کن. این الگو، پایه پردازش Permalink در وردپرس است.

اگر Permalink کار نکند و خطای 404 رخ دهد، ممکن است این بلوک به‌درستی تنظیم نشده باشد. برای مطالعه بیشتر، مقاله راهنمای کامل رفع خطای پیوند یکتای وردپرس را ببینید.

بهینه‌سازی FastCGI و PHP-FPM

پس از پیکربندی پایه، باید FastCGI و PHP-FPM را بهینه کرد تا پتانسیل کامل Nginx استفاده شود.

پارامترهای ضروری FastCGI

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param HTTPS $https if_not_empty;
    fastcgi_param HTTP_PROXY "";
    
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
    fastcgi_busy_buffers_size 64k;
    fastcgi_read_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_connect_timeout 60;
}

توضیح پارامترها:

  • fastcgi_buffers: تعداد و اندازه بافرها برای خواندن پاسخ از PHP-FPM.
  • fastcgi_buffer_size: اندازه بافر برای خط اول پاسخ.
  • fastcgi_busy_buffers_size: حداکثر بافر قابل استفاده هنگام ارسال پاسخ به کلاینت.
  • fastcgi_read_timeout: حداکثر زمان انتظار برای پاسخ PHP-FPM.
  • fastcgi_send_timeout: حداکثر زمان ارسال درخواست به PHP-FPM.

مقادیر Buffer باید بر اساس اندازه پاسخ‌های PHP تنظیم شوند. اگر این مقادیر کم باشند، Nginx مجبور به نوشتن پاسخ‌های بزرگ در فایل موقت روی دیسک می‌شود که عملکرد را کاهش می‌دهد.

تنظیم Buffer و Timeout

client_max_body_size 64M;
client_body_buffer_size 128k;
client_header_buffer_size 1k;
large_client_header_buffers 4 16k;
client_body_timeout 60s;
client_header_timeout 60s;
send_timeout 60s;
keepalive_timeout 65;

تنظیم client_max_body_size به‌ویژه برای سایت‌های ووکامرسی که آپلود تصاویر محصولات دارند، ضروری است. مقدار پیش‌فرض ۱ مگابایت است که برای آپلود تصاویر با کیفیت پایین کافی است، اما برای تصاویر حرفه‌ای، باید افزایش یابد. اگر این تنظیم نادرست باشد، کاربران با خطای ۴۱۳ مواجه می‌شوند. برای مطالعه بیشتر، مقاله خطای آپلود فایل در وردپرس را ببینید.

مدیریت PHP-FPM Pools

PHP-FPM از Pool‌ها برای مدیریت گروه‌های process استفاده می‌کند. تنظیمات Pool در فایل‌های /etc/php/8.2/fpm/pool.d/*.conf قرار دارند:

[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500

pm.status_path = /status
ping.path = /ping

request_terminate_timeout = 300s
request_slowlog_timeout = 10s
slowlog = /var/log/php-fpm/slow.log

توضیح مقادیر کلیدی:

  • pm.max_children: حداکثر تعداد process فرزند. باید بر اساس حافظه سرور محاسبه شود: (حافظه کل - حافظه سیستم) / متوسط مصرف هر process.
  • pm.start_servers: تعداد process در زمان راه‌اندازی.
  • pm.max_requests: حداکثر تعداد درخواست قبل از restart process. مقدار ۵۰۰ تا ۱۰۰۰ توصیه می‌شود تا نشت حافظه مدیریت شود.
  • request_terminate_timeout: حداکثر زمان اجرای یک درخواست.
  • slowlog: فایل ثبت درخواست‌های کند.

در سرورهایی که چند سایت وردپرسی اجرا می‌کنند، استفاده از Pool‌های جداگانه توصیه می‌شود. برای مطالعه بیشتر، مقاله راه‌اندازی VPS امن برای میزبانی وردپرس را ببینید.

FastCGI Cache و کش در سطح سرور

FastCGI Cache یکی از قوی‌ترین قابلیت‌های Nginx است که می‌تواند پاسخ‌های PHP-FPM را کش کند. این مکانیزم، بار روی PHP و دیتابیس را به‌شدت کاهش می‌دهد:

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=WORDPRESS:100m inactive=60m max_size=1g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

server {
    # ...
    
    set $skip_cache 0;
    
    # درخواست‌های POST کش نمی‌شوند
    if ($request_method = POST) {
        set $skip_cache 1;
    }
    
    # Query Stringها کش نمی‌شوند
    if ($query_string != "") {
        set $skip_cache 1;
    }
    
    # صفحات پویا کش نمی‌شوند
    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
        set $skip_cache 1;
    }
    
    # کاربران وارد شده کش نمی‌شوند
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }
    
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        
        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 301 302 60m;
        fastcgi_cache_valid 404 1m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        
        add_header X-FastCGI-Cache $upstream_cache_status;
    }
}

هدر X-FastCGI-Cache وضعیت کش را در پاسخ HTTP نشان می‌دهد: HIT، MISS، BYPASS یا EXPIRED. این هدر برای عیب‌یابی بسیار مفید است.

برای درک بیشتر درباره استراتژی‌های کش، مقاله بهترین افزونه‌های کش وردپرس را ببینید. ترکیب FastCGI Cache با کش افزونه‌ای می‌تواند عملکرد چشمگیری ایجاد کند.

بهینه‌سازی فایل‌های استاتیک

فایل‌های استاتیک (تصاویر، CSS، JavaScript، فونت) بخش بزرگی از ترافیک سایت‌های وردپرسی را تشکیل می‌دهند. بهینه‌سازی سرو این فایل‌ها، تأثیر مستقیمی بر سرعت سایت دارد.

Expires و Cache-Control

location ~* \.(jpg|jpeg|png|gif|ico|webp|avif|svg)$ {
    expires 365d;
    add_header Cache-Control "public, immutable";
    access_log off;
    log_not_found off;
}

location ~* \.(css|js)$ {
    expires 30d;
    add_header Cache-Control "public";
    access_log off;
}

location ~* \.(woff|woff2|ttf|otf|eot)$ {
    expires 365d;
    add_header Cache-Control "public, immutable";
    access_log off;
}

location ~* \.(mp4|webm|ogg|mp3|wav)$ {
    expires 30d;
    add_header Cache-Control "public";
}

ترکیب expires و Cache-Control تضمین می‌کند که مرورگر فایل‌ها را برای مدت طولانی کش کند. مقدار immutable به مرورگر می‌گوید که فایل تغییر نخواهد کرد و نیازی به revalidate نیست.

Gzip و Brotli Compression

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
           application/json application/javascript application/xml+rss
           application/rss+xml application/atom+xml image/svg+xml
           application/vnd.ms-fontobject application/x-font-ttf
           font/opentype;
gzip_disable "msie6";
gzip_min_length 256;

Brotli یک الگوریتم فشرده‌سازی مدرن است که فشرده‌سازی بهتری از Gzip ارائه می‌دهد. اگر ماژول Brotli در Nginx نصب باشد:

brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript
             application/json application/javascript application/xml+rss
             application/rss+xml application/atom+xml image/svg+xml
             application/vnd.ms-fontobject application/x-font-ttf
             font/opentype;

ترکیب Gzip و Brotli اطمینان می‌دهد که همه مرورگرها، صرف‌نظر از پشتیبانی، از فشرده‌سازی بهره‌مند شوند. برای مقایسه فشرده‌سازی و سرعت، مقاله چگونه زمان بارگذاری سایت را کاهش دهیم را ببینید.

پشتیبانی از WebP و AVIF

WebP و AVIF فرمت‌های تصویری مدرنی هستند که حجم کمتری نسبت به JPEG و PNG دارند. Nginx می‌تواند به‌طور خودکار درخواست‌های تصویر را به این فرمت‌ها هدایت کند:

map $http_accept $webp_suffix {
    default "";
    "~*webp" ".webp";
}

map $http_accept $avif_suffix {
    default "";
    "~*avif" ".avif";
}

location ~* \.(png|jpg|jpeg)$ {
    add_header Vary Accept;
    try_files $uri$avif_suffix $uri$webp_suffix $uri =404;
    expires 365d;
    add_header Cache-Control "public, immutable";
}

این پیکربندی ابتدا تلاش می‌کند نسخه AVIF را سرو کند، اگر پشتیبانی شود؛ سپس WebP؛ و در نهایت تصویر اصلی. برای مطالعه بیشتر، مقاله بهترین فرمت تصویر برای وب کدام است؟ را ببینید.

پیکربندی امنیتی Nginx

امنیت در Nginx از چند لایه تشکیل می‌شود. در این بخش، مهم‌ترین لایه‌ها بررسی می‌شود.

مخفی‌سازی فایل‌های حساس

location ~ /\.ht {
    deny all;
}

location = /wp-config.php {
    deny all;
}

location ~* /(?:uploads|files)/.*\.php$ {
    deny all;
}

location ~* \.(conf|log|sh|bak|sql|swp|dist)$ {
    deny all;
}

location ~* /(?:readme|license|changelog|license)\.(html|txt|md)$ {
    deny all;
}

این قوانین از دسترسی به فایل‌های حساس جلوگیری می‌کنند. به‌ویژه، مسدودسازی اجرای فایل‌های PHP در پوشه uploads، از یکی از رایج‌ترین روش‌های نفوذ جلوگیری می‌کند. برای مطالعه بیشتر درباره امنیت، مقاله چگونه سایت وردپرسی را در برابر هک محافظت کنیم؟ را ببینید.

هدرهای امنیتی

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

هر هدر نقش مشخصی دارد:

  • X-Frame-Options: جلوگیری از Clickjacking.
  • X-Content-Type-Options: جلوگیری از MIME Sniffing.
  • X-XSS-Protection: فعال‌سازی فیلتر XSS در مرورگرهای قدیمی.
  • Referrer-Policy: کنترل اطلاعات ارسالی در هدر Referer.
  • Permissions-Policy: محدودسازی دسترسی به APIهای مرورگر.
  • HSTS: اجبار مرورگر به استفاده از HTTPS.

برای مطالعه بیشتر درباره این هدرها، مقاله هدرهای امنیتی HTTP چه کاربردی دارند؟ را ببینید.

Rate Limiting

Rate Limiting یکی از مؤثرترین راه‌های مقابله با حملات Brute Force و DDoS است:

limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
    # ...
    
    location = /wp-login.php {
        limit_req zone=login burst=3 nodelay;
        limit_conn addr 5;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
    
    location = /xmlrpc.php {
        deny all;
    }
    
    location / {
        limit_req zone=general burst=50 nodelay;
        limit_conn addr 20;
        try_files $uri $uri/ /index.php?$args;
    }
}

این قوانین:

  • ورود به wp-login.php را به ۵ درخواست در دقیقه محدود می‌کند.
  • دسترسی به xmlrpc.php را کاملاً مسدود می‌کند (اگر نیازی به آن نیست).
  • درخواست‌های عمومی را به ۳۰ درخواست در ثانیه محدود می‌کند.

برای مطالعه بیشتر، مقاله چگونه حملات brute force را در وردپرس دفع کنیم؟ را ببینید.

مسدودسازی wp-login و xmlrpc

برای سایت‌هایی که به xmlrpc.php نیازی ندارند (اکثر سایت‌های مدرن)، مسدودسازی کامل آن توصیه می‌شود. همچنین، محدودسازی wp-login.php به IPهای مشخص یا فعال‌سازی Basic Auth روی آن، امنیت را افزایش می‌دهد:

location = /wp-login.php {
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

پیکربندی Nginx برای ووکامرس

ووکامرس (WooCommerce) نیازمند پیکربندی خاصی است، زیرا بخشی از صفحات آن پویا و وابسته به سشن کاربر هستند.

استثنای سبد خرید و پرداخت از کش

set $skip_cache 0;

if ($request_uri ~* "/cart/|/checkout/|/my-account/|/wc-api/|/addons/") {
    set $skip_cache 1;
}

if ($http_cookie ~* "woocommerce_items_in_cart|woocommerce_cart_hash|wp_woocommerce_session_") {
    set $skip_cache 1;
}

if ($request_method = POST) {
    set $skip_cache 1;
}

if ($query_string != "") {
    set $skip_cache 1;
}

این قوانین تضمین می‌کنند که:

  • صفحات سبد خرید و پرداخت هرگز کش نمی‌شوند.
  • کاربران دارای آیتم در سبد خرید، نسخه کش‌شده نمی‌بینند.
  • درخواست‌های POST همیشه پویا پردازش می‌شوند.

صفحات سفارش و پیگیری

location ~* /(?:order-received|order-pay|view-order) {
    set $skip_cache 1;
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}

صفحات سفارش، اطلاعات حساس مشتری را نمایش می‌دهند و هرگز نباید کش شوند. برای مطالعه بیشتر، مقاله امنیت ووکامرس چه نکاتی دارد؟ را ببینید.

کش تصاویر محصولات

location ~* /wp-content/uploads/.*\.(jpg|jpeg|png|gif|webp|avif)$ {
    expires 365d;
    add_header Cache-Control "public, immutable";
    access_log off;
    log_not_found off;
    try_files $uri $uri/ /index.php?$args;
}

تصاویر محصولات به‌ندرت تغییر می‌کنند، بنابراین کش طولانی‌مدت توصیه می‌شود. برای مطالعه بیشتر، مقاله بهینه‌سازی دیتابیس ووکامرس را ببینید.

پیکربندی SSL/TLS حرفه‌ای

امنیت SSL/TLS فراتر از نصب گواهی است. پیکربندی دقیق، امنیت و عملکرد را به‌طور همزمان بهبود می‌دهد.

نسخه‌های TLS و Cipher Suites

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

نکات کلیدی:

  • فقط TLS 1.2 و 1.3 مجاز باشند. نسخه‌های قدیمی‌تر (SSL 3.0، TLS 1.0، TLS 1.1) ناامن هستند.
  • ترتیب Cipher Suites باید بر اساس امنیت و عملکرد تنظیم شود.
  • Session Cache و Session Tickets، زمان handshake را کاهش می‌دهند.
  • OCSP Stapling، زمان تأیید گواهی را کاهش می‌دهد.

HSTS و Preload

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

HSTS مرورگر را ملزم می‌کند که همیشه از HTTPS استفاده کند، حتی اگر کاربر HTTP وارد کند. مقدار preload به مرورگر می‌گوید که این دامنه در لیست HSTS preload قرار گیرد. توجه: HSTS را فقط زمانی فعال کنید که مطمئن هستید سایت همیشه HTTPS خواهد بود.

OCSP Stapling

OCSP Stapling یک مکانیزم است که در آن، سرور وضعیت اعتبار گواهی خود را از CA دریافت می‌کند و آن را همراه با گواهی به مرورگر ارائه می‌دهد. این کار، یک رفت‌و‌برگشت به سرور CA را حذف می‌کند و زمان handshake را کاهش می‌دهد:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

برای مطالعه بیشتر درباره SSL، مقاله SSL چیست و چرا سایت به آن نیاز ضروری دارد؟ را ببینید.

Reverse Proxy و معماری‌های ترکیبی

در معماری‌های پیشرفته، Nginx می‌تواند به‌عنوان Reverse Proxy در جلوی Apache، Node.js یا سرویس‌های دیگر قرار گیرد:

server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 300s;
    }
}

این معماری، امکان ترکیب بهترین ویژگی‌های چند سرور را فراهم می‌کند. برای مطالعه بیشتر درباره معماری‌های ترکیبی، مقاله نقش CDN در معماری وب را ببینید.

لاگ‌گیری و پایش

لاگ‌های Nginx منبع ارزشمندی برای عیب‌یابی و پایش هستند.

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for" '
                'rt=$request_time uct="$upstream_connect_time" '
                'uht="$upstream_header_time" urt="$upstream_response_time"';

access_log /var/log/nginx/access.log main buffer=32k flush=5s;
error_log /var/log/nginx/error.log warn;

پارامترهای $request_time، $upstream_response_time و $upstream_header_time زمان‌بندی دقیق پردازش درخواست را نشان می‌دهند. این اطلاعات برای شناسایی گلوگاه‌ها حیاتی هستند. برای مطالعه بیشتر، مقاله چگونه خطاهای سرور را در لاگ‌ها بررسی کنیم؟ را ببینید.

عیب‌یابی خطاهای رایج Nginx

حتی با پیکربندی دقیق، برخی خطاها ممکن است رخ دهند. شناخت این خطاها، زمان عیب‌یابی را کاهش می‌دهد.

خطاهای 502 و 504

خطای 502 Bad Gateway معمولاً به‌دلیل عدم پاسخگویی PHP-FPM رخ می‌دهد:

  • PHP-FPM متوقف شده است.
  • سوکت PHP-FPM در مسیر اشتباه است.
  • محدودیت pm.max_children به پایان رسیده است.
  • Permission سوکت یونیکس اشتباه است.

برای عیب‌یابی:

# بررسی وضعیت PHP-FPM
systemctl status php8.2-fpm

# بررسی سوکت
ls -la /run/php/php8.2-fpm.sock

# بررسی لاگ
tail -100 /var/log/php8.2-fpm.log
tail -100 /var/log/nginx/error.log

خطای 504 Gateway Timeout زمانی رخ می‌دهد که PHP-FPM در زمان مقرر پاسخ ندهد. راه‌حل، افزایش fastcgi_read_timeout یا بهینه‌سازی کد PHP است. برای مطالعه بیشتر، مقاله رفع خطای 504 Gateway Timeout را ببینید.

حلقه‌های ریدایرکت

حلقه‌های ریدایرکت معمولاً به‌دلیل پیکربندی نادرست HTTPS یا WordPress Address و Site Address رخ می‌دهند:

# بررسی تنظیمات وردپرس
wp option get siteurl
wp option get home

# بررسی هدرها
curl -I https://example.com

اگر وردپرس تصور کند که HTTPS فعال نیست، ممکن است به HTTP ریدایرکت کند و این چرخه ادامه یابد. راه‌حل، تنظیم هدر X-Forwarded-Proto است:

fastcgi_param HTTPS on;
fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;

برای مطالعه بیشتر، مقاله آیا حلقه ریدایرکت بی‌نهایت سایت وردپرس شما را فلج کرده است؟ را ببینید.

اگر Permalink کار نکند و همه صفحات به‌جز صفحه اصلی خطای 404 بدهند، احتمالاً بلوک try_files درست تنظیم نشده است:

location / {
    try_files $uri $uri/ /index.php?$args;
}

همچنین، باید مطمئن شوید که تنظیمات Permalink در پیشخوان وردپرس به‌درستی تنظیم شده و فایل .htaccess نیازی نیست. برای مطالعه بیشتر، مقاله راهنمای کامل رفع خطای پیوند یکتای وردپرس را ببینید.

پرسش‌های پرتکرار درباره Nginx و وردپرس

در این بخش، به پرسش‌های متداول پاسخ داده می‌شود. این ساختار برای بهینه‌سازی محتوا برای موتورهای پاسخگو (Answer Engines) نیز مفید است.

Nginx چیست و چه تفاوتی با Apache دارد؟

Nginx یک وب‌سرور event-driven است که هزاران اتصال همزمان را با مصرف حافظه کم مدیریت می‌کند. Apache از مدل process/thread per request استفاده می‌کند که در بارهای بالا منابع بیشتری مصرف می‌کند.

آیا Nginx از فایل htaccess پشتیبانی می‌کند؟

خیر. Nginx فقط از فایل‌های پیکربندی سراسری استفاده می‌کند. قوانین rewrite و امنیتی باید در فایل پیکربندی Nginx نوشته شوند، نه در .htaccess.

چگونه WordPress را روی Nginx راه‌اندازی کنم؟

با نصب Nginx، PHP-FPM و MySQL، سپس پیکربندی بلوک server با تنظیمات try_files، fastcgi_pass و قوانین امنیتی. برای شروع، می‌توانید از پیکربندی‌های آماده موجود در مستندات رسمی استفاده کنید.

FastCGI Cache چیست و چگونه کار می‌کند؟

FastCGI Cache یک مکانیزم کش در Nginx است که پاسخ‌های PHP-FPM را ذخیره می‌کند. در درخواست‌های بعدی، پاسخ از کش سرو می‌شود و بار روی PHP و دیتابیس کاهش می‌یابد.

چرا سایت من روی Nginx خطای 502 می‌دهد؟

خطای 502 معمولاً به‌دلیل عدم پاسخگویی PHP-FPM رخ می‌دهد. دلایل: توقف PHP-FPM، سوکت اشتباه، محدودیت pm.max_children یا مشکل در Permission.

چگونه Permalink را در Nginx تنظیم کنم؟

با استفاده از بلوک try_files $uri $uri/ /index.php?$args; در location /.

آیا Nginx برای فروشگاه ووکامرس مناسب است؟

بله، به‌شرط پیکربندی درست. باید صفحات سبد خرید، پرداخت و حساب کاربری از کش مستثنی شوند.

چگونه Rate Limiting را در Nginx فعال کنم؟

با استفاده از limit_req_zone و limit_req در بلوک‌های location. این تنظیمات به‌ویژه برای wp-login.php و درخواست‌های عمومی مفید است.

تفاوت FastCGI Cache و کش افزونه چیست؟

FastCGI Cache در سطح Nginx عمل می‌کند و کل پاسخ HTML را کش می‌کند. کش افزونه در سطح PHP عمل می‌کند و بخش‌هایی از محتوا را کش می‌کند. ترکیب هر دو می‌تواند عملکرد بهتری ارائه دهد.

چگونه از فایل‌های حساس در Nginx محافظت کنم؟

با قوانین location برای مسدودسازی دسترسی به wp-config.php، .htaccess، فایل‌های PHP در پوشه uploads و فایل‌های backup.

آیا Nginx می‌تواند به‌عنوان Reverse Proxy برای Apache عمل کند؟

بله. Nginx در جلوی Apache قرار می‌گیرد، فایل‌های استاتیک را سرو می‌کند و درخواست‌های PHP را به Apache ارسال می‌کند. این معماری، مزایای هر دو سرور را ترکیب می‌کند.

چگونه Brotli Compression را فعال کنم؟

Brotli در Nginx به‌طور پیش‌فرض نصب نیست. باید ماژول ngx_brotli را نصب کنید و سپس با brotli on; فعال کنید.

آیا Nginx روی هاست اشتراکی در دسترس است؟

بسیاری از هاست‌های اشتراکی Nginx را به‌عنوان وب‌سرور اصلی یا Reverse Proxy استفاده می‌کنند، اما امکان ویرایش فایل پیکربندی را به کاربر نمی‌دهند. برای پیکربندی کامل، نیاز به VPS یا سرور اختصاصی است. برای مطالعه بیشتر، مقاله VPS چیست و چه تفاوتی با هاست اشتراکی دارد؟ را ببینید.

چگونه تغییرات پیکربندی را اعمال و تست کنم؟

nginx -t
systemctl reload nginx

دستور nginx -t پیکربندی را بررسی می‌کند و خطاها را گزارش می‌دهد. اگر تست موفق بود، با systemctl reload nginx تغییرات اعمال می‌شوند بدون قطع سرویس.

نکات پیشرفته برای مهندسان ارشد

برای مهندسان ارشد و تیم‌های DevOps، پیکربندی Nginx یک مسئله چندلایه است. در ادامه، به نکات پیشرفته‌ای می‌پردازیم که در پروژه‌های بزرگ حیاتی می‌شوند.

تحلیل کارایی با OpenTracing

در محیط‌های تولیدی، پایش دقیق زمان‌بندی درخواست‌ها ضروری است:

log_format tracing '$remote_addr [$time_local] "$request" '
                   '$status $body_bytes_sent rt=$request_time '
                   'uct=$upstream_connect_time urt=$upstream_response_time '
                   'uht=$upstream_header_time request_id=$request_id';

map $http_x_request_id $request_id {
    default $http_x_request_id;
    ""      $request_id;
}

ترکیب request_id با ابزارهایی مانند Jaeger یا Zipkin، امکان ردیابی توزیع‌شده را فراهم می‌کند.

Lua و OpenResty

OpenResty نسخه‌ای از Nginx است که با LuaJIT ترکیب شده و امکان اجرای کد Lua در زمان پردازش درخواست را فراهم می‌کند. این قابلیت، امکاناتی مانند:

  • احراز هویت داینامیک
  • Rate Limiting پیشرفته
  • تغییر محتوا در لبه
  • کش هوشمند
location /protected {
    access_by_lua_block {
        local token = ngx.req.get_headers()["Authorization"]
        if not token or not validate_token(token) then
            ngx.exit(ngx.HTTP_UNAUTHORIZED)
        end
    }
    proxy_pass http://backend;
}

Zero-Downtime Deployment

در معماری‌های حرفه‌ای، استقرار باید بدون قطع سرویس انجام شود:

upstream wordpress {
    server 127.0.0.1:9000;
    server 127.0.0.1:9001 backup;
    keepalive 32;
}

server {
    location ~ \.php$ {
        fastcgi_pass wordpress;
        # ...
    }
}

با تغییر مسیر deployment و reload Nginx، می‌توان بدون قطع سرویس، نسخه جدید را مستقر کرد. برای مطالعه بیشتر، مقاله CI/CD برای پروژه‌های وردپرسی را ببینید.

HTTP/2 و HTTP/3

HTTP/2 و HTTP/3 بهبودهای چشمگیری در عملکرد ارائه می‌دهند:

# HTTP/2
listen 443 ssl http2;

# HTTP/3 (نیازمند Nginx 1.25+)
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';

HTTP/2 با multiplexing، امکان ارسال چندین درخواست روی یک اتصال را فراهم می‌کند. HTTP/3 بر پایه QUIC، تأخیر را در شبکه‌های ناپایدار کاهش می‌دهد.

Image Resizing در لبه

با Nginx می‌توان تصاویر را در لبه تغییر اندازه داد، بدون نیاز به پیش‌پردازش:

location ~ ^/images/(?\d+)/(?\d+)/(?.*)$ {
    set $w $width;
    set $h $height;
    image_filter resize $w $h;
    image_filter_jpeg_quality 85;
    image_filter_buffer 10M;
    try_files /images/$image =404;
}

این قابلیت نیازمند ماژول ngx_http_image_filter_module است.

Docker و Nginx

در معماری‌های Docker، Nginx می‌تواند به‌عنوان Reverse Proxy برای container وردپرس عمل کند:

upstream wordpress {
    server wordpress:9000;
}

server {
    location ~ \.php$ {
        fastcgi_pass wordpress;
    }
}

برای مطالعه بیشتر، مقاله تجربه کار با Docker در توسعه پروژه‌ها را ببینید.

مقایسه پیکربندی‌های مختلف

سناریوپیکربندیمزیتمحدودیت
سایت کوچکNginx + PHP-FPM + MySQLساده و سریعمحدود در مقیاس
فروشگاه متوسطNginx + FastCGI Cache + Redisعملکرد بالاپیچیدگی بیشتر
سایت بزرگNginx + OpenResty + Microservicesمقیاس‌پذیری بالانیازمند تیم متخصص
MultisiteNginx + WordPress Multisiteمدیریت متمرکزپیچیدگی در rewrite
HeadlessNginx + REST API + Frontendانعطاف معمارینیازمند توسعه بیشتر

نکات کلیدی برای پایداری بلندمدت

در پایان، چند نکته کلیدی که باید در خاطر بماند:

  • همیشه nginx -t را پیش از reload اجرا کنید: از قطع سرویس جلوگیری می‌کند.
  • لاگ‌ها را با پارامترهای زمان‌بندی تنظیم کنید: $request_time و $upstream_response_time.
  • FastCGI Cache را با هوشمندی تنظیم کنید: استثنا کردن صفحات پویا.
  • امنیت را لایه‌بندی کنید: هدرها، Rate Limiting، مخفی‌سازی فایل‌ها.
  • SSL/TLS را با استانداردهای مدرن تنظیم کنید: فقط TLS 1.2 و 1.3.
  • HTTP/2 و HTTP/3 را فعال کنید: بهبود عملکرد با تغییر کم.
  • PHP-FPM را دقیق تنظیم کنید: بر اساس حافظه سرور.
  • پایش مستمر داشته باشید: با ابزارهایی مانند Prometheus و Grafana.
  • مستندسازی کنید: پیکربندی را در Git نگهداری کنید.
  • آموزش تیم: همه اعضا با پیکربندی Nginx آشنا باشند.
  • پیکربندی را ماژولار کنید: استفاده از include برای بخش‌های مشترک.
  • تست بار بگیرید: با ابزارهایی مانند wrk یا ab، پیکربندی را در بار تست کنید.

اگر تجربه پیکربندی Nginx برای وردپرس را داشته‌اید و به بهینه‌سازی خاصی رسیده‌اید، جالب است بدانم کدام تنظیم بیشترین تأثیر را در سرعت یا پایداری سایت شما داشته است. تجربه خودتان را در دیدگاه‌ها بنویسید؛ به‌خصوص اگر راه‌حل خلاقانه‌ای برای سناریوی خاصی پیدا کرده‌اید که می‌تواند برای دیگران مفید باشد.