برای اجرای سایت‌ها و برنامه‌های PHP روی Nginx، نصب خود PHP به‌تنهایی کافی نیست. برخلاف Apache که می‌تواند از ماژول‌هایی مانند mod_php استفاده کند، Nginx موتور داخلی برای اجرای کد PHP ندارد. به همین دلیل، درخواست‌های مربوط به فایل‌های PHP باید از طریق پروتکل FastCGI به سرویس PHP-FPM ارسال شوند.

پیکربندی PHP-FPM با Nginx یکی از مهم‌ترین مراحل راه‌اندازی یک سرور LEMP است. اگر مسیر Socket، سطح دسترسی فایل‌ها، تنظیمات Pool یا بخش fastcgi_pass اشتباه باشد، ممکن است سایت به‌جای اجرا فایل PHP را دانلود کند، با خطای ۵۰۲ Bad Gateway روبه‌رو شود یا مصرف RAM و CPU سرور به‌شدت افزایش پیدا کند.

در این راهنما، نصب PHP-FPM روی Ubuntu، ساخت Pool اختصاصی برای هر سایت، اتصال Nginx به PHP-FPM، استفاده از Unix Socket یا TCP، تنظیم سطح دسترسی، تست اجرای PHP، مانیتورینگ Workerها، بهینه‌سازی Process Manager و رفع خطاهای رایج را مرحله‌به‌مرحله بررسی می‌کنیم.

سطح مقاله: متوسط | مناسب برای: مدیران سرور، کاربران VPS، توسعه‌دهندگان PHP، مدیران سایت وردپرسی، متخصصان DevOps و افرادی که از Nginx به‌عنوان وب‌سرور استفاده می‌کنند.

فهرست مطالب

PHP-FPM چیست؟

PHP-FPM مخفف PHP FastCGI Process Manager است. این سرویس مجموعه‌ای از پردازش‌های PHP را مدیریت می‌کند و درخواست‌های دریافت‌شده از وب‌سرور را اجرا می‌کند.

PHP-FPM معمولاً شامل این اجزا است:

  • Master Process: پردازش اصلی که Poolها و Workerها را مدیریت می‌کند.
  • Worker Process: پردازش‌هایی که فایل‌های PHP را اجرا می‌کنند.
  • Pool: مجموعه‌ای از Workerها با کاربر، Socket و محدودیت منابع مشخص.
  • Unix Socket یا TCP Port: مسیری که Nginx از طریق آن درخواست را به PHP-FPM تحویل می‌دهد.

برای مثال، وقتی کاربر صفحه index.php را باز می‌کند، Nginx درخواست را دریافت می‌کند؛ اما اجرای فایل را به PHP-FPM می‌سپارد. PHP-FPM کد را اجرا می‌کند، خروجی HTML را به Nginx برمی‌گرداند و Nginx پاسخ نهایی را برای مرورگر ارسال می‌کند.

Nginx و PHP-FPM چگونه با هم کار می‌کنند؟

فرایند اجرای یک درخواست PHP معمولاً به این شکل است:

  1. مرورگر آدرس https://example.com/index.php را درخواست می‌کند.
  2. Nginx درخواست را دریافت و Server Block مربوط به دامنه را انتخاب می‌کند.
  3. بخش location ~ \.php$ تشخیص می‌دهد که درخواست مربوط به PHP است.
  4. Nginx اطلاعات درخواست را با FastCGI به PHP-FPM ارسال می‌کند.
  5. PHP-FPM یکی از Workerهای آزاد را برای اجرای فایل انتخاب می‌کند.
  6. خروجی اجرای PHP به Nginx بازگردانده می‌شود.
  7. Nginx پاسخ نهایی را برای کاربر ارسال می‌کند.

در این ساختار، Nginx معمولاً فایل‌های استاتیک مانند تصویر، CSS و JavaScript را مستقیماً ارائه می‌کند و فقط درخواست‌های PHP را به PHP-FPM می‌فرستد. این تفکیک می‌تواند کارایی و کنترل منابع سرور را بهبود دهد.

نسخه PHP-FPM در Ubuntu ۲۲.۰۴، ۲۴.۰۴ و ۲۶.۰۴

مسیر سرویس، پوشه Pool و Socket به نسخه PHP بستگی دارد. بنابراین قبل از ادامه، نسخه Ubuntu و PHP را بررسی کنید:

lsb_release -rs
php -v
نسخه Ubuntuنسخه پیش‌فرض PHPنام سرویسSocket پیش‌فرض
Ubuntu 22.04PHP 8.1php8.1-fpm/run/php/php8.1-fpm.sock
Ubuntu 24.04PHP 8.3php8.3-fpm/run/php/php8.3-fpm.sock
Ubuntu 26.04PHP 8.5php8.5-fpm/run/php/php8.5-fpm.sock

نکته مهم: جدول بالا مربوط به مخازن پیش‌فرض Ubuntu است. اگر PHP را از Repository دیگری نصب کرده باشید، ممکن است نسخه، مسیر و نام سرویس متفاوت باشد.

برای مشاهده Socketهای واقعی موجود روی سرور از این دستور استفاده کنید:

ls -lah /run/php/

پیش‌نیازهای نصب

برای اجرای مراحل مقاله به موارد زیر نیاز دارید:

  • یک سرور Ubuntu ۲۲.۰۴، ۲۴.۰۴ یا ۲۶.۰۴
  • دسترسی SSH
  • کاربر دارای دسترسی sudo
  • یک دامنه متصل به IP سرور
  • پورت‌های ۸۰ و ۴۴۳ باز در فایروال
  • آشنایی پایه با دستورات لینوکس

این ساختار برای اجرا روی سرور مجازی ایران، سرور مجازی آلمان یا سرور اختصاصی مناسب است. در هاست اشتراکی معمولاً دسترسی لازم برای ویرایش Poolهای PHP-FPM در اختیار کاربر قرار ندارد.

نصب Nginx و PHP-FPM

ابتدا فهرست پکیج‌ها را به‌روزرسانی کنید:

sudo apt update

سپس Nginx را نصب کنید:

sudo apt install nginx -y

برای نصب PHP-FPM باید نسخه متناسب با سیستم‌عامل خود را انتخاب کنید.

Ubuntu 22.04

sudo apt install php8.1-fpm php8.1-cli -y

Ubuntu 24.04

sudo apt install php8.3-fpm php8.3-cli -y

Ubuntu 26.04

sudo apt install php8.5-fpm php8.5-cli -y

در Ubuntu ۲۴.۰۴ و ۲۶.۰۴ می‌توانید از Meta Package زیر نیز استفاده کنید:

sudo apt install php-fpm php-cli -y

برای سایت‌های معمول PHP و وردپرس، افزونه‌های پرکاربرد را نیز نصب کنید. در مثال زیر عبارت 8.3 را با نسخه PHP خود جایگزین کنید:

sudo apt install \
php8.3-mysql \
php8.3-curl \
php8.3-gd \
php8.3-mbstring \
php8.3-xml \
php8.3-zip \
php8.3-intl \
php8.3-bcmath \
php8.3-opcache -y

بررسی سرویس و Socket مربوط به PHP-FPM

سرویس‌های Nginx و PHP-FPM را فعال و اجرا کنید:

sudo systemctl enable --now nginx
sudo systemctl enable --now php8.3-fpm

وضعیت PHP-FPM:

sudo systemctl status php8.3-fpm

باید وضعیت زیر را مشاهده کنید:

active (running)

برای مشاهده Socket:

ls -l /run/php/php8.3-fpm.sock

همچنین می‌توانید فایل Pool پیش‌فرض را بررسی کنید:

grep -E '^listen\s*=' /etc/php/8.3/fpm/pool.d/www.conf

خروجی معمولاً مشابه این است:

listen = /run/php/php8.3-fpm.sock

ساخت مسیر سایت و کاربر اختصاصی

برای امنیت بهتر، مخصوصاً وقتی چند سایت روی یک سرور میزبانی می‌شوند، بهتر است هر سایت کاربر Unix و PHP-FPM Pool اختصاصی داشته باشد.

ابتدا گروه و کاربر را ایجاد کنید:

sudo groupadd example_user

sudo useradd \
  -g example_user \
  -d /var/www/example.com \
  -s /usr/sbin/nologin \
  example_user

مسیر سایت را بسازید:

sudo mkdir -p /var/www/example.com/public

مالکیت مسیر را تنظیم کنید:

sudo chown -R example_user:example_user /var/www/example.com

سطح دسترسی پیشنهادی اولیه:

sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;

داشتن Pool جداگانه باعث می‌شود فایل‌ها و Workerهای هر سایت از سایت‌های دیگر جدا شوند و بتوانید برای هر دامنه محدودیت منابع مستقل تعریف کنید.

ساخت PHP-FPM Pool اختصاصی

فایل Poolها در مسیر زیر قرار دارند:

/etc/php/VERSION/fpm/pool.d/

برای PHP ۸.۳ یک فایل جدید بسازید:

sudo nano /etc/php/8.3/fpm/pool.d/example.com.conf

محتوای زیر را وارد کنید:

[example_com]

user = example_user
group = example_user

listen = /run/php/php8.3-fpm-example.com.sock

listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 4
pm.max_requests = 500

request_terminate_timeout = 120s
request_slowlog_timeout = 5s
slowlog = /var/log/php8.3-fpm-example.com-slow.log

php_admin_value[error_log] = /var/log/php8.3-fpm-example.com-error.log
php_admin_flag[log_errors] = on

php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M
php_admin_value[memory_limit] = 256M
php_admin_value[max_execution_time] = 120

clear_env = yes
security.limit_extensions = .php

توضیح تنظیمات مهم Pool

گزینهکاربرد
[example_com]نام منحصربه‌فرد Pool
user و groupکاربری که Workerهای PHP با آن اجرا می‌شوند
listenمسیر Socket یا آدرس TCP برای دریافت درخواست‌ها
listen.ownerمالک Socket؛ باید برای کاربر Nginx قابل دسترسی باشد
pmروش مدیریت Workerها
pm.max_childrenحداکثر تعداد درخواست‌های PHP هم‌زمان
pm.max_requestsتعداد درخواست پیش از بازیابی هر Worker
request_terminate_timeoutحداکثر زمان اجرای یک درخواست
slowlogمسیر ثبت درخواست‌های PHP کند

بعد از ذخیره فایل، صحت تنظیمات PHP-FPM را بررسی کنید:

sudo php-fpm8.3 -t

در صورت نبود خطا، سرویس را Reload کنید:

sudo systemctl reload php8.3-fpm

وجود Socket جدید را بررسی کنید:

ls -l /run/php/php8.3-fpm-example.com.sock

پیکربندی Server Block در Nginx

یک فایل جدید برای دامنه بسازید:

sudo nano /etc/nginx/sites-available/example.com

پیکربندی زیر را وارد کنید:

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.php index.html index.htm;

    access_log /var/log/nginx/example.com-access.log;
    error_log /var/log/nginx/example.com-error.log;

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

    location ~ \.php$ {
        try_files $uri =404;

        include snippets/fastcgi-php.conf;

        fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;

        fastcgi_read_timeout 120;
        fastcgi_connect_timeout 30;
        fastcgi_send_timeout 120;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }

    location ~* \.(?:css|js|jpg|jpeg|gif|png|svg|webp|ico|woff|woff2)$ {
        expires 30d;
        access_log off;
        log_not_found off;
    }
}

نقش SCRIPT_FILENAME

PHP-FPM باید مسیر واقعی فایل PHP روی دیسک را دریافت کند. در Ubuntu، فایل زیر معمولاً این پارامترها را تنظیم می‌کند:

include snippets/fastcgi-php.conf;

اگر این Snippet روی سیستم شما وجود ندارد، می‌توانید پارامترهای ضروری را مستقیم بنویسید:

include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $document_root;

استفاده از try_files $uri =404; پیش از ارسال درخواست به PHP-FPM باعث می‌شود فقط فایل PHP واقعاً موجود اجرا شود.

فعال‌سازی سایت

sudo ln -s \
/etc/nginx/sites-available/example.com \
/etc/nginx/sites-enabled/example.com

در صورت نیاز، سایت پیش‌فرض را غیرفعال کنید:

sudo rm -f /etc/nginx/sites-enabled/default

تنظیمات Nginx را تست کنید:

sudo nginx -t

اگر خروجی موفق بود:

sudo systemctl reload nginx

تست تنظیمات Nginx و PHP-FPM

یک فایل تست PHP بسازید:

echo '<?php phpinfo(); ?>' | \
sudo tee /var/www/example.com/public/info.php

مالکیت آن را اصلاح کنید:

sudo chown example_user:example_user \
/var/www/example.com/public/info.php

حالا آدرس زیر را در مرورگر باز کنید:

http://example.com/info.php

در صفحه PHP Info این موارد را بررسی کنید:

  • Server API باید برابر FPM/FastCGI باشد.
  • نسخه PHP باید همان نسخه موردنظر باشد.
  • مقادیر memory_limit و upload_max_filesize باید با Pool هماهنگ باشند.
  • فایل php.ini بارگذاری‌شده باید مربوط به مسیر FPM باشد.

پس از تست، فایل PHP Info را فوراً حذف کنید؛ چون اطلاعات حساس سرور را نمایش می‌دهد:

sudo rm /var/www/example.com/public/info.php

برای تست از خط فرمان نیز می‌توانید استفاده کنید:

curl -I http://example.com

تفاوت Unix Socket و TCP در FastCGI

Nginx می‌تواند از دو روش به PHP-FPM متصل شود:

اتصال با Unix Socket

fastcgi_pass unix:/run/php/php8.3-fpm.sock;

Unix Socket برای زمانی مناسب است که Nginx و PHP-FPM روی یک سرور اجرا می‌شوند.

مزایا:

  • عدم نیاز به باز کردن پورت شبکه
  • کنترل دسترسی با مالک و Permission فایل Socket
  • پیاده‌سازی ساده برای یک سرور

اتصال با TCP

در فایل Pool:

listen = 127.0.0.1:9000

در Nginx:

fastcgi_pass 127.0.0.1:9000;

TCP معمولاً در این سناریوها استفاده می‌شود:

  • Nginx و PHP-FPM در کانتینرهای جدا اجرا می‌شوند.
  • PHP-FPM روی سرور دیگری قرار دارد.
  • ارتباط از طریق شبکه Docker یا Kubernetes انجام می‌شود.
  • Load Balancing بین چند PHP-FPM Backend لازم است.

اگر TCP استفاده می‌کنید، PHP-FPM را بدون فایروال و احراز امنیتی روی اینترنت عمومی باز نکنید. بهتر است سرویس فقط روی localhost، شبکه خصوصی یا VPN قابل دسترسی باشد.

امن‌سازی PHP-FPM و Nginx

اجرای هر سایت با کاربر مستقل

اجرای همه سایت‌ها با کاربر مشترک www-data باعث می‌شود در صورت نفوذ به یک سایت، دسترسی به فایل‌های سایت‌های دیگر ساده‌تر شود. برای سرورهای چندسایته، Pool جدا با کاربر اختصاصی توصیه می‌شود.

محدود کردن پسوندهای قابل اجرا

در فایل Pool:

security.limit_extensions = .php

با این تنظیم، PHP-FPM فقط فایل‌های دارای پسوند PHP را اجرا می‌کند.

جلوگیری از اجرای PHP در پوشه Upload

برای وردپرس می‌توانید اجرای PHP در مسیر Upload را ببندید:

location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}

مخفی کردن فایل‌های حساس

location ~ /\.(?!well-known).* {
    deny all;
}

برای وردپرس:

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

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

غیرفعال کردن نمایش خطا در Production

در Pool یا php.ini:

php_admin_flag[display_errors] = off
php_admin_flag[log_errors] = on

نمایش خطا به کاربران ممکن است مسیر فایل‌ها، Queryها و اطلاعات داخلی برنامه را افشا کند.

فعال‌سازی HTTPS

بعد از اطمینان از اجرای صحیح سایت، گواهی SSL نصب کنید و تمام درخواست‌های HTTP را به HTTPS منتقل کنید.

تنظیم Process Manager در PHP-FPM

PHP-FPM سه روش اصلی برای مدیریت Workerها دارد:

حالت static

pm = static
pm.max_children = 10

همیشه تعداد ثابتی Worker فعال است. این حالت برای ترافیک پایدار و سرور دارای RAM کافی قابل استفاده است، اما در زمان کم‌ترافیک نیز حافظه مصرف می‌کند.

حالت dynamic

pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 4

PHP-FPM تعداد Workerها را متناسب با ترافیک کم و زیاد می‌کند. این حالت برای بسیاری از سایت‌های Production انتخاب مناسبی است.

حالت ondemand

pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 10s

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

چطور pm.max_children را محاسبه کنیم؟

هر PHP-FPM Worker مقداری RAM مصرف می‌کند. اگر تعداد Workerها بیش از ظرفیت سرور باشد، سیستم وارد Swap می‌شود یا سرویس‌ها توسط OOM Killer متوقف می‌شوند.

ابتدا مصرف حافظه Workerهای PHP را بررسی کنید:

ps --no-headers -o rss,cmd -C php-fpm8.3

یا:

ps -ylC php-fpm8.3 --sort:rss

برای محاسبه متوسط مصرف Workerها:

ps --no-headers -o rss -C php-fpm8.3 | \
awk '{sum+=$1; count++} END {
if (count > 0) print sum/count/1024 " MB"
}'

فرمول تقریبی:

pm.max_children =
RAM قابل اختصاص به PHP-FPM ÷ متوسط RAM هر Worker

مثال:

  • RAM کل سرور: ۴ گیگابایت
  • RAM رزروشده برای سیستم، Nginx و دیتابیس: ۲ گیگابایت
  • RAM قابل اختصاص به PHP-FPM: ۲ گیگابایت
  • مصرف متوسط هر Worker: ۸۰ مگابایت
2048 ÷ 80 = 25

در این سناریو می‌توان مقدار محافظه‌کارانه‌ای مانند ۲۰ تا ۲۲ برای pm.max_children در نظر گرفت و سپس با مانیتورینگ واقعی آن را تنظیم کرد.

هشدار: مقدار زیاد pm.max_children الزاماً سایت را سریع‌تر نمی‌کند. اگر CPU، دیتابیس یا RAM ظرفیت کافی نداشته باشد، افزایش Workerها می‌تواند سرور را کندتر کند.

فعال‌سازی صفحه وضعیت PHP-FPM

در فایل Pool این گزینه را اضافه کنید:

pm.status_path = /fpm-status

در Server Block مربوط به Nginx:

location = /fpm-status {
    include fastcgi_params;

    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

    fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;

    allow 127.0.0.1;
    allow YOUR_MONITORING_IP;
    deny all;

    access_log off;
}

پس از Reload سرویس‌ها:

sudo systemctl reload php8.3-fpm
sudo systemctl reload nginx

از داخل سرور تست کنید:

curl http://127.0.0.1/fpm-status

اطلاعات صفحه Status شامل موارد زیر است:

  • تعداد Workerهای فعال و بیکار
  • تعداد کل درخواست‌های پردازش‌شده
  • طول صف درخواست‌ها
  • بیشترین تعداد Workerهای فعال
  • تعداد دفعات رسیدن به سقف Workerها

این صفحه نباید بدون محدودیت IP در دسترس اینترنت قرار گیرد.

فعال‌سازی Slow Log در PHP-FPM

Slow Log برای پیدا کردن اسکریپت‌های کند، افزونه‌های سنگین، Queryهای طولانی و درخواست‌هایی که Workerها را مشغول نگه می‌دارند کاربرد دارد.

در فایل Pool:

request_slowlog_timeout = 5s
slowlog = /var/log/php8.3-fpm-example.com-slow.log

بعد از Reload، درخواست‌هایی که بیش از پنج ثانیه طول بکشند در فایل Slow Log ثبت می‌شوند:

sudo tail -f /var/log/php8.3-fpm-example.com-slow.log

لاگ خطا:

sudo tail -f /var/log/php8.3-fpm-example.com-error.log

ساخت Pool جداگانه برای چند سایت

فرض کنید سه سایت روی یک سرور دارید:

site1.com
site2.com
shop.example.com

برای هر سایت می‌توان یک کاربر، Pool و Socket مستقل ساخت:

/run/php/php8.3-fpm-site1.sock
/run/php/php8.3-fpm-site2.sock
/run/php/php8.3-fpm-shop.sock

مزایای این ساختار:

  • جداسازی امنیتی فایل‌ها و پردازش‌ها
  • تعیین memory_limit مستقل
  • تعیین pm.max_children مستقل
  • ثبت Error Log و Slow Log جداگانه
  • امکان اجرای سایت‌ها با نسخه‌های متفاوت PHP
  • جلوگیری از مصرف تمام Workerها توسط یک سایت پرترافیک

در Server Block هر سایت، فقط Socket همان Pool را قرار دهید:

fastcgi_pass unix:/run/php/php8.3-fpm-site1.sock;

تنظیم PHP-FPM و Nginx برای وردپرس

برای وردپرس، بخش اصلی Nginx معمولاً به این شکل است:

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

location ~ \.php$ {
    try_files $uri =404;

    include snippets/fastcgi-php.conf;

    fastcgi_pass unix:/run/php/php8.3-fpm-wordpress.sock;
}

location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}

افزونه‌های موردنیاز وردپرس و WooCommerce معمولاً شامل این موارد هستند:

php-mysql
php-curl
php-gd
php-mbstring
php-xml
php-zip
php-intl
php-bcmath
php-opcache

برای سایت‌های پرترافیک می‌توان Redis Object Cache، FastCGI Cache یا Page Cache را نیز بررسی کرد. اگر مدیریت سرور و تنظیم PHP-FPM برایتان پیچیده است، استفاده از هاست وردپرس مدیریت‌شده می‌تواند نیاز به تنظیم دستی Workerها و وب‌سرور را کاهش دهد.

رفع خطای ۵۰۲ Bad Gateway در Nginx و PHP-FPM

خطای ۵۰۲ معمولاً یعنی Nginx نتوانسته از PHP-FPM پاسخ معتبر دریافت کند.

مرحله اول: بررسی اجرای PHP-FPM

sudo systemctl status php8.3-fpm

اگر سرویس متوقف است:

sudo systemctl restart php8.3-fpm

مرحله دوم: تطبیق مسیر Socket

مسیر تعریف‌شده در Nginx را بررسی کنید:

grep -R "fastcgi_pass" /etc/nginx/sites-enabled/

مسیر تعریف‌شده در PHP-FPM:

grep -R "^listen\s*=" /etc/php/8.3/fpm/pool.d/

این دو مسیر باید دقیقاً یکسان باشند.

مرحله سوم: بررسی وجود Socket

ls -lah /run/php/

اگر Socket وجود ندارد، احتمالاً Pool بارگذاری نشده یا فایل کانفیگ خطا دارد:

sudo php-fpm8.3 -t
sudo journalctl -u php8.3-fpm -n 100 --no-pager

مرحله چهارم: بررسی Permission مربوط به Socket

ls -l /run/php/php8.3-fpm-example.com.sock

کاربر Nginx که معمولاً www-data است باید اجازه اتصال به Socket را داشته باشد:

listen.owner = www-data
listen.group = www-data
listen.mode = 0660

مرحله پنجم: بررسی لاگ Nginx

sudo tail -f /var/log/nginx/example.com-error.log

پیام‌های رایج:

connect() to unix:/run/php/... failed
Permission denied
No such file or directory
Connection refused
upstream timed out

مرحله ششم: بررسی Timeout

اگر اسکریپت واقعاً زمان زیادی نیاز دارد:

fastcgi_read_timeout 300;

و در Pool:

request_terminate_timeout = 300s

افزایش Timeout نباید جایگزین عیب‌یابی اسکریپت یا Query کند. ابتدا علت کندی را با Slow Log و لاگ دیتابیس بررسی کنید.

خطاهای رایج دیگر

فایل PHP به‌جای اجرا دانلود می‌شود

این مشکل معمولاً یعنی بخش PHP در Server Block وجود ندارد یا فایل کانفیگ سایت فعال نشده است.

بررسی کنید این بخش وجود داشته باشد:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

سپس:

sudo nginx -t
sudo systemctl reload nginx

خطای File not found

علت‌های رایج:

  • مقدار root اشتباه است.
  • پارامتر SCRIPT_FILENAME درست تنظیم نشده است.
  • فایل PHP در مسیر موردنظر وجود ندارد.
  • Nginx و PHP-FPM مسیرهای متفاوتی را در کانتینر می‌بینند.

خطای Permission denied

مالکیت فایل‌ها را بررسی کنید:

namei -l /var/www/example.com/public/index.php

این دستور Permission تمام پوشه‌های مسیر را نشان می‌دهد.

بررسی مالکیت:

ls -lah /var/www/example.com/public/

خطای pool seems busy

اگر در لاگ پیام‌هایی درباره Busy شدن Pool یا رسیدن به pm.max_children مشاهده می‌کنید، ممکن است:

  • تعداد Workerها کم باشد.
  • اسکریپت‌ها یا Queryها کند باشند.
  • ترافیک ناگهانی افزایش یافته باشد.
  • ربات‌ها یا حمله HTTP منابع را اشغال کرده باشند.
  • سرویس خارجی باعث معطل ماندن درخواست‌ها شده باشد.

قبل از افزایش Workerها، Slow Log، مصرف RAM، CPU، دیتابیس و Access Log را بررسی کنید.

مقدار php.ini تغییر نمی‌کند

PHP CLI و PHP-FPM فایل‌های php.ini جداگانه دارند.

مسیر PHP CLI:

/etc/php/8.3/cli/php.ini

مسیر PHP-FPM:

/etc/php/8.3/fpm/php.ini

بعد از تغییر تنظیمات FPM:

sudo systemctl reload php8.3-fpm

چک‌لیست امنیت و عملکرد PHP-FPM با Nginx

  • نسخه واقعی PHP پیش از ویرایش مسیرها بررسی شده باشد.
  • Nginx و PHP-FPM از Socket یا TCP یکسان استفاده کنند.
  • برای هر سایت مهم Pool و کاربر جداگانه ساخته شود.
  • Socket فقط برای کاربر لازم قابل دسترسی باشد.
  • security.limit_extensions روی .php تنظیم شود.
  • فایل‌های PHP فقط در صورت وجود به PHP-FPM ارسال شوند.
  • اجرای PHP در پوشه Upload مسدود شود.
  • نمایش خطا در Production غیرفعال و ثبت لاگ فعال باشد.
  • صفحه PHP Info بعد از تست حذف شود.
  • صفحه FPM Status با IP محدود شود.
  • Slow Log برای پیدا کردن درخواست‌های کند فعال باشد.
  • pm.max_children بر اساس RAM واقعی محاسبه شود.
  • مقادیر Timeout بدون دلیل بیش از حد افزایش پیدا نکنند.
  • PHP، Nginx و Ubuntu مرتب به‌روزرسانی شوند.
  • HTTPS و گواهی SSL معتبر فعال باشد.
  • از فایل‌های Nginx، Poolها و php.ini بکاپ گرفته شود.

سوالات متداول درباره PHP-FPM و Nginx

PHP-FPM چیست؟

PHP-FPM یک Process Manager برای PHP است که مجموعه‌ای از Workerها را برای اجرای اسکریپت‌های PHP مدیریت می‌کند و درخواست‌ها را از طریق FastCGI دریافت می‌کند.

آیا Nginx بدون PHP-FPM می‌تواند PHP اجرا کند؟

خیر. Nginx موتور داخلی اجرای PHP ندارد و برای اجرای فایل‌های PHP باید درخواست را به PHP-FPM یا یک FastCGI Handler دیگر ارسال کند.

fastcgi_pass چیست؟

دستور fastcgi_pass در Nginx مقصد ارسال درخواست‌های FastCGI را مشخص می‌کند. مقصد می‌تواند Unix Socket یا یک IP و پورت TCP باشد.

Unix Socket بهتر است یا TCP؟

اگر Nginx و PHP-FPM روی یک سرور هستند، Unix Socket معمولاً انتخاب ساده و امنی است. اگر سرویس‌ها روی کانتینر یا سرورهای جدا قرار دارند، TCP مناسب‌تر است.

علت خطای ۵۰۲ Bad Gateway چیست؟

رایج‌ترین علت‌ها توقف سرویس PHP-FPM، اشتباه بودن مسیر Socket، Permission نامناسب Socket، Crash کردن Workerها یا Timeout درخواست است.

چطور بفهمیم PHP-FPM در حال اجرا است؟

sudo systemctl status php8.3-fpm

نام سرویس را با نسخه PHP نصب‌شده جایگزین کنید.

چطور مسیر Socket مربوط به PHP-FPM را پیدا کنیم؟

ls -lah /run/php/
grep -R "^listen\s*=" /etc/php/*/fpm/pool.d/

Pool در PHP-FPM چیست؟

Pool مجموعه‌ای از Workerهای PHP با کاربر، گروه، Socket، محدودیت حافظه و تنظیمات Process Manager مستقل است.

آیا برای هر سایت باید Pool جدا بسازیم؟

برای یک سایت ساده استفاده از Pool پیش‌فرض کافی است؛ اما روی سرورهای چندسایته، ساخت Pool جداگانه امنیت، کنترل منابع و عیب‌یابی را بهبود می‌دهد.

pm.max_children چه کاری انجام می‌دهد؟

این گزینه حداکثر تعداد Workerهای هم‌زمان PHP-FPM را مشخص می‌کند. در عمل، این مقدار سقف تعداد درخواست‌های PHP است که یک Pool می‌تواند هم‌زمان اجرا کند.

چرا تغییرات php.ini روی سایت اعمال نمی‌شود؟

احتمالاً فایل php.ini مربوط به CLI را تغییر داده‌اید، در حالی که Nginx از php.ini مربوط به FPM استفاده می‌کند. پس از تغییر فایل FPM نیز باید سرویس PHP-FPM Reload شود.

جمع‌بندی

پیکربندی PHP-FPM با Nginx پایه اجرای صحیح و پایدار سایت‌های PHP روی وب‌سرور Nginx است. Nginx درخواست HTTP را دریافت می‌کند، فایل‌های استاتیک را مستقیماً ارائه می‌دهد و اجرای PHP را از طریق FastCGI به PHP-FPM می‌سپارد.

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

همچنین تنظیم صحیح pm.max_children، فعال‌سازی Slow Log، محدودسازی صفحه Status، جلوگیری از اجرای PHP در پوشه‌های Upload و بررسی لاگ‌های Nginx و PHP-FPM نقش مهمی در امنیت و پایداری سرور دارند.

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

منابع پیشنهادی برای مطالعه بیشتر