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.
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.
Nginx 对接 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 自己处理静态文件,只把 .php 请求经 Unix socket(开销更低)或 TCP 9000 端口转发给 FPM。单一入口 index.php 加 try_files 实现 Laravel 的美化 URL。
FPM 进程池调优
; /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
max_children ≈ 可用内存 ÷ 单进程平均常驻内存,并给 Nginx 与数据库留余量;观察 fpm status 页可知峰值并发。
OPcache 与安全加固
- OPcache:生产环境 opcache.enable=1、validate_timestamps=0(发布后 opcache:reset),memory_consumption 按代码量调整。
- 隐藏版本:expose_php=Off、display_errors=Off,错误写日志。
- 固定 session 存储路径,按需禁用危险函数(exec、system),全站 HTTPS。
- 零停机发布:symlink 切换(current → releases/x)加 opcache:reset,优于重启 fpm。