Nginx with PHP-FPM

PHP-FPM Installation

Ubuntu/Debian

# Install PHP and PHP-FPM
sudo apt update
sudo apt install php php-fpm php-mysql php-gd php-curl php-zip -y
 
# Start and enable PHP-FPM
sudo systemctl start php-fpm
sudo systemctl enable php-fpm
 
# Or for specific version
sudo systemctl start php8.1-fpm
sudo systemctl enable php8.1-fpm
 
# Verify installation
php -v
php-fpm -v

CentOS/RHEL

# Install PHP and PHP-FPM
sudo yum install php php-fpm php-mysql php-gd php-curl php-zip -y
 
# Start and enable PHP-FPM
sudo systemctl start php-fpm
sudo systemctl enable php-fpm
 
# Verify installation
php -v

Basic Nginx PHP-FPM Configuration

server {
    listen 80;
    server_name example.com;
 
    root /var/www/example.com/public;
 
    index index.php index.html index.htm;
 
    # Handle PHP files
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
 
    # Deny access to hidden files
    location ~ /\. {
        deny all;
    }
}

Advanced Nginx Configuration with Gzip

server {
    listen 80;
    server_name example.com www.example.com;
 
    root /var/www/example.com/public;
 
    # Enable gzip compression
    gzip on;
    gzip_types
        application/atom+xml
        application/geo+json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rdf+xml
        application/rss+xml
        application/xhtml+xml
        application/xml
        font/eot
        font/otf
        font/ttf
        image/svg+xml
        text/css
        text/javascript
        text/plain
        text/xml;
    
    gzip_vary on;
    gzip_proxied no-cache no-store private expired auth;
    gzip_min_length 1000;
    gzip_disable "MSIE [1-6]\.";
 
    index index.php;
 
    # Rewrite rules for Laravel/Symfony
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
 
    # Handle PHP files
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
 
    # Deny access to hidden files and directories
    location ~ /\. {
        deny all;
    }
 
    # Deny access to .htaccess files
    location ~ /\.ht {
        deny all;
    }
}

SSL Configuration (HTTPS)

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}
 
# HTTPS server
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
 
    root /var/www/example.com/public;
 
    # SSL certificates
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 
    # SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
 
    index index.php;
 
    # Rewrite for Laravel/Symfony
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
 
    # Handle PHP files
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
 
    location ~ /\. {
        deny all;
    }
 
    location ~ /\.ht {
        deny all;
    }
}

PHP-FPM Socket Configuration

Socket Types

# Unix socket (recommended for same server)
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
 
# TCP socket (for separate servers)
fastcgi_pass 127.0.0.1:9000;
 
# Different PHP versions
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;

Check PHP-FPM Socket Location

# Find PHP-FPM socket
sudo find /run -name "*.sock" -type s | grep php
 
# Common locations:
# Ubuntu/Debian: /run/php/php8.1-fpm.sock
# CentOS: /var/run/php-fpm/php-fpm.sock
 
# Check PHP-FPM pool config
cat /etc/php/8.1/fpm/pool.d/www.conf | grep listen

PHP-FPM Optimization

Edit PHP-FPM Pool Configuration

# Ubuntu/Debian
sudo nano /etc/php/8.1/fpm/pool.d/www.conf
 
# CentOS
sudo nano /etc/php-fpm.d/www.conf

Optimization Settings

; Process management
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
 
; Request timeout
request_terminate_timeout = 60
 
; Slow request logging
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5
 
; Error logging
error_log = /var/log/php-fpm/error.log

Apply Configuration Changes

# Reload PHP-FPM
sudo systemctl reload php8.1-fpm
# Or
sudo systemctl reload php-fpm
 
# Restart PHP-FPM
sudo systemctl restart php8.1-fpm
 
# Verify changes
sudo systemctl status php8.1-fpm

Monitoring PHP-FPM

# Check PHP-FPM status
sudo systemctl status php8.1-fpm
 
# View PHP-FPM logs
tail -f /var/log/php-fpm/error.log
tail -f /var/log/php-fpm/slow.log
 
# Monitor processes
ps aux | grep php-fpm
 
# Check pool status (if enabled)
curl http://127.0.0.1/fpm_status.php

Troubleshooting

# Connection refused error
# 1. Check if PHP-FPM is running
sudo systemctl status php8.1-fpm
 
# 2. Check socket exists
ls -la /run/php/php8.1-fpm.sock
 
# 3. Check Nginx can access socket
sudo -u www-data test -w /run/php/php8.1-fpm.sock
 
# 4. Check Nginx error log
tail -f /var/log/nginx/error.log
 
# Permission denied
# Fix socket permissions
sudo chown www-data:www-data /run/php/php8.1-fpm.sock
sudo chmod 660 /run/php/php8.1-fpm.sock