کانفیگ nginx برای PHP-FPM (لاراول و وردپرس)

nginx خودش PHP اجرا نمی‌کند؛ درخواست‌های فایل‌های php را به PHP-FPM می‌دهد. این راهنما کانفیگ کامل و امن را برای لاراول و وردپرس نشان می‌دهد.

وب‌سرور و SSLمتوسط12 دقیقه

۱نصب PHP-FPM و افزونه‌های رایج

نسخهٔ PHP را با توجه به پروژه انتخاب کنید (اینجا 8.3). نام سوکت هم به همین نسخه بستگی دارد.

bash
sudo apt update
sudo apt install -y php8.3-fpm php8.3-mysql php8.3-mbstring php8.3-xml php8.3-curl php8.3-zip php8.3-gd php8.3-intl
systemctl status php8.3-fpm --no-pager
ls /run/php/

۲کانفیگ لاراول (Laravel)

ریشهٔ سایت باید پوشهٔ public باشد، نه ریشهٔ پروژه، تا فایل‌های .env و کد از بیرون در دسترس نباشند.

nginx
server {
    listen 80;
    listen [::]:80;
    server_name example.com;

    root /var/www/laravel/public;
    index index.php;

    charset utf-8;
    client_max_body_size 20m;

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

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_read_timeout 60s;
    }

    # فایل‌های مخفی (به‌جز .well-known برای certbot)
    location ~ /\.(?!well-known).* {
        deny all;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }
}

۳کانفیگ وردپرس (WordPress)

تفاوت اصلی در try_files است که باید آرگومان‌ها را به index.php بدهد. اجرای فایل‌های php داخل پوشهٔ uploads را هم ببندید.

nginx
server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/wordpress;
    index index.php;
    client_max_body_size 64m;

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

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

    # امنیت: اجرای PHP داخل uploads ممنوع
    location ~* /wp-content/uploads/.*\.php$ {
        deny all;
    }

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

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

۴دسترسی فایل‌ها

کاربر PHP-FPM (www-data) باید بتواند فایل‌ها را بخواند و در پوشه‌های storage و uploads بنویسد. فایل‌ها را ۶۴۴ و پوشه‌ها را ۷۵۵ نگه دارید و فقط پوشه‌های نوشتنی را در اختیار www-data بگذارید.

bash
sudo chown -R www-data:www-data /var/www/laravel/storage /var/www/laravel/bootstrap/cache
sudo find /var/www/laravel -type f -exec chmod 644 {} \;
sudo find /var/www/laravel -type d -exec chmod 755 {} \;

هرگز از chmod 777 استفاده نکنید؛ همیشه راه امن‌تری وجود دارد.

۵تنظیم php.ini برای آپلود و حافظه

برای آپلود فایل بزرگ باید هم nginx (client_max_body_size) و هم PHP را تغییر دهید.

ini
sudo nano /etc/php/8.3/fpm/php.ini

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 60

۶اعمال تغییرات

کانفیگ nginx را تست و سرویس‌ها را reload کنید.

bash
sudo nginx -t && sudo systemctl reload nginx
sudo systemctl restart php8.3-fpm

۷عیب‌یابی

اگر مرورگر فایل PHP را دانلود می‌کند یعنی بلوک php فعال نیست. خطای 502 معمولاً یعنی سوکت PHP-FPM اشتباه است. لاگ‌ها را ببینید.

bash
sudo tail -n 30 /var/log/nginx/error.log
sudo tail -n 30 /var/log/php8.3-fpm.log
ls -l /run/php/php8.3-fpm.sock

پرسش‌های پرتکرار دربارهٔ کانفیگ nginx برای PHP-FPM (لاراول و وردپرس)

خطای «File not found» با nginx و PHP یعنی چه؟

معمولاً مسیر SCRIPT_FILENAME درست نیست یا root اشتباه است. مطمئن شوید root به پوشهٔ درست اشاره می‌کند و fastcgi_param SCRIPT_FILENAME تنظیم شده است.

چرا آپلود فایل بزرگ با خطای 413 مواجه می‌شود؟

مقدار client_max_body_size در nginx کم است (پیش‌فرض ۱ مگابایت). آن را بالا ببرید و upload_max_filesize و post_max_size در php.ini را هم تنظیم کنید.