Deploying PHP: Nginx + PHP-FPM

How Nginx hands requests to PHP-FPM over FastCGI, tuning fpm pool workers, OPcache settings, and hardening a production deployment.

AdvancedUpdated 2026-10-2836K views

Nginx to PHP-FPM

server {
    listen 80;
    server_name example.com;
    root /var/www/shop/public;
    index index.php;

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

    location ~ \.php$ {
        fastcgi_pass   unix:/run/php/php8.3-fpm.sock;  # 或 127.0.0.1:9000
        fastcgi_index  index.php;
        include        fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~ /\.(env|git) { deny all; }   # 保护敏感文件
}

Nginx serves static files itself and forwards only .php requests to FPM over a Unix socket (lower overhead) or TCP port 9000. The single entry index.php plus try_files gives Laravel pretty URLs.

FPM Pool Tuning

; /etc/php/8.3/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock

; dynamic:按需在 pm.min/max 之间 fork
pm = dynamic
pm.max_children = 60        ; 每个进程约 30-50MB,按内存反推
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 1000      ; 处理 N 个请求后重启,防泄漏

; 慢日志定位卡顿接口
request_slowlog_timeout = 3s
slowlog = /var/log/php/slow.log
Estimate max_children as (available RAM) / (average per-process RSS), leaving headroom for Nginx and the database; the fpm status page (?json) shows the peak concurrent count.

OPcache and Hardening

  • OPcache: opcache.enable=1, validate_timestamps=0 in production (deploy runs opcache:reset), memory_consumption sized to the codebase.
  • Hide versions: expose_php=Off, display_errors=Off, log_errors=On to a file.
  • Lock down session save path, disable dangerous functions (exec, system) when unneeded, and serve over HTTPS.
  • Zero-downtime deploys: symlink switch (current -> releases/x) plus opcache:reset beats restarting fpm.

Friends & Partners