nginx + PHP-FPM Production Config
Also Known As
nginx config
PHP-FPM pool
fastcgi
production PHP setup
TL;DR
The canonical nginx + PHP-FPM setup for PHP production — nginx handles static files and slow clients, PHP-FPM runs PHP via FastCGI, with proper timeout, buffer, and security settings.
Explanation
nginx as a reverse proxy in front of PHP-FPM provides: serving static files directly (no PHP overhead), buffering slow client uploads before passing to FPM (protecting worker count), SSL termination, gzip compression, and security headers. PHP-FPM pool configuration controls worker count, memory limits, and request timeouts. Key settings: pm.max_children (max concurrent PHP processes), pm.max_requests (restart workers after N requests to prevent memory leaks), fastcgi_read_timeout (PHP execution time limit in nginx).
Common Misconception
✗ More PHP-FPM workers always means better performance — each worker consumes ~30-60MB; too many workers exhaust RAM and cause swapping, which is worse than fewer workers.
Why It Matters
A misconfigured nginx/PHP-FPM stack is one of the most common causes of PHP application performance problems — timeouts, worker exhaustion, and memory leaks all stem from missing configuration.
Common Mistakes
- pm.max_children set too high — workers exceed available RAM, causing swap and severe slowdowns.
- No fastcgi_read_timeout — nginx kills long-running PHP processes before they complete.
- Not setting PHP-FPM pm.max_requests — workers accumulate memory leaks without restarts.
- Missing fastcgi_param PHP_VALUE to override php.ini per virtual host.
Code Examples
✗ Vulnerable
# Minimal nginx config — missing critical settings:
server {
listen 80;
root /var/www/html;
index index.php;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# No timeout, no buffering, no security headers
}
}
; php-fpm.conf — no limits:
pm = dynamic
pm.max_children = 50 ; May exceed available RAM
✓ Fixed
# Production nginx config:
server {
listen 443 ssl http2;
root /var/www/html/public;
# Serve static files directly:
location ~* \.(css|js|png|jpg|woff2)$ {
expires 1y; add_header Cache-Control 'public, immutable';
}
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_read_timeout 30;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
}
}
; php-fpm pool.conf:
pm = dynamic
pm.max_children = 20 ; RAM / ~50MB per worker
pm.max_requests = 500 ; Restart after 500 requests
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
16 Mar 2026
Edited
28 Apr 2026
Views
26
AI edit
PF Media Bot
Claude Opus 4.5 on bad_code · 28 Apr 2026
Edits history 1 edit
- bad_code PF Media Bot Claude Opus 4.5 · 28 Apr 2026
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
Amazonbot 7
Perplexity 4
SEMrush 3
Unknown AI 2
Ahrefs 2
Google 1
Majestic 1
Also referenced
How they use it
crawler 20
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Medium
⚡ Quick Fix
Serve PHP via fastcgi_pass unix:/run/php/php8.3-fpm.sock; set fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name to prevent path traversal via Nginx
📦 Applies To
PHP 5.0+
web
🔗 Prerequisites
🔍 Detection Hints
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name without realpath; missing try_files preventing 404 PHP execution
Auto-detectable:
✓ Yes
nginxconfig.io
mozilla-ssl-config
⚠ Related Problems
🤖 AI Agent
Confidence: Medium
False Positives: Medium
✗ Manual fix
Fix: Medium
Context: File
CWE-16