PHP-FPM

PHP-FPM #

PHP masih mendominasi web — WordPress, Laravel, Drupal, Magento, dan ribuan aplikasi lain dibangun dengan PHP. Caddy mendukung PHP melalui FastCGI protocol dengan direktif php_fastcgi yang sangat mudah dikonfigurasi dibanding Nginx.

Cara Kerja PHP di Caddy #

Browser → HTTPS Request → Caddy
                              │
                              ├─ Static files (CSS, JS, images) → Caddy langsung
                              │
                              └─ PHP files → FastCGI → PHP-FPM → PHP → Response

Instalasi PHP-FPM #

# Ubuntu/Debian
sudo apt install php8.3-fpm php8.3-mysql php8.3-curl \
    php8.3-gd php8.3-mbstring php8.3-xml php8.3-zip \
    php8.3-redis php8.3-imagick

# Start dan enable
sudo systemctl enable --now php8.3-fpm
sudo systemctl status php8.3-fpm

# Socket PHP-FPM (lebih cepat dari TCP)
ls /run/php/
# php8.3-fpm.sock

Konfigurasi Dasar PHP #

example.com {
    root * /var/www/html
    
    # Aktifkan PHP via FastCGI socket
    php_fastcgi unix//run/php/php8.3-fpm.sock
    
    # Sajikan file statis secara langsung
    file_server
}

WordPress #

wordpress.example.com {
    root * /var/www/wordpress
    
    encode gzip zstd
    
    # Security: Blokir akses ke file sensitif
    @blocked {
        path /wp-admin/includes/*
        path /wp-includes/theme-compat/*
        path /wp-includes/js/tinymce/langs/*
        path *.sql
        path */.git/*
        path */.env*
        path */xmlrpc.php
    }
    respond @blocked 403
    
    # WordPress pretty permalinks
    php_fastcgi unix//run/php/php8.3-fpm.sock
    
    file_server
    
    # Rewrite untuk pretty URLs (WordPress Rewrite Rules)
    @notFound `!{path} =~ "^/wp-"`
    try_files {path} {path}/ /index.php?{query}
}

Laravel #

laravel.example.com {
    # Laravel serve dari direktori public/
    root * /var/www/laravel/public
    
    encode gzip zstd
    
    # Security headers
    header {
        -Server
        -X-Powered-By
        X-Frame-Options "SAMEORIGIN"
        X-Content-Type-Options "nosniff"
    }
    
    # Semua request yang bukan file statis → index.php
    php_fastcgi unix//run/php/php8.3-fpm.sock
    
    file_server
    
    # Laravel front controller pattern
    try_files {path} {path}/ /index.php?{query}
}

Keamanan File Sensitif PHP #

example.com {
    root * /var/www/html
    
    # Blokir akses ke file konfigurasi
    @sensitive {
        path /.env
        path /.env.*
        path /config.php
        path /wp-config.php
        path /.git*
        path /.htaccess
        path /composer.json
        path /composer.lock
        path /package.json
        path /package-lock.json
        path *.sql
        path *.bak
        path *.log
    }
    respond @sensitive 403
    
    # Hanya izinkan PHP dieksekusi dari root, bukan subdirektori upload
    @phpInUpload path /uploads/*.php /media/*.php
    respond @phpInUpload 403
    
    php_fastcgi unix//run/php/php8.3-fpm.sock
    file_server
}

Upload File Besar #

{
    # Global: izinkan request body besar untuk upload
    servers {
        max_header_size 1mb
    }
}

uploads.example.com {
    root * /var/www/uploads-app
    
    encode gzip zstd
    
    # Tingkatkan timeout untuk upload besar
    php_fastcgi unix//run/php/php8.3-fpm.sock {
        read_timeout 300s    # 5 menit untuk upload besar
        dial_timeout 10s
    }
    
    # Batasi ukuran upload di level Caddy juga
    request_body {
        max_size 100mb       # Tolak request > 100MB
    }
    
    file_server
}
; php.ini settings yang diperlukan
; /etc/php/8.3/fpm/php.ini
upload_max_filesize = 100M
post_max_size = 105M
max_execution_time = 300
max_input_time = 300
memory_limit = 256M

Multiple PHP Version #

# PHP 8.3 untuk aplikasi modern
app-modern.example.com {
    root * /var/www/modern-app
    php_fastcgi unix//run/php/php8.3-fpm.sock
    file_server
    try_files {path} {path}/ /index.php?{query}
}

# PHP 7.4 untuk aplikasi legacy
app-legacy.example.com {
    root * /var/www/legacy-app
    php_fastcgi unix//run/php/php7.4-fpm.sock
    file_server
    try_files {path} {path}/ /index.php?{query}
}
# Install PHP 7.4 di samping PHP 8.3
sudo apt install php7.4-fpm php7.4-mysql php7.4-curl

# Keduanya berjalan di socket berbeda
ls /run/php/
# php7.4-fpm.sock
# php8.3-fpm.sock

PHP-FPM Pool Tuning #

; /etc/php/8.3/fpm/pool.d/www.conf

[www]
user = www-data
group = www-data

; Socket (lebih cepat dari TCP untuk koneksi lokal)
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; Dynamic process management
pm = dynamic
pm.max_children = 50         ; Maksimal worker process
pm.start_servers = 5          ; Worker saat startup
pm.min_spare_servers = 5      ; Minimum worker idle
pm.max_spare_servers = 35     ; Maksimum worker idle
pm.max_requests = 500         ; Restart worker setelah N request (cegah memory leak)

; Logging
php_admin_value[error_log] = /var/log/php8.3-fpm/error.log
php_admin_flag[log_errors] = on

; Keamanan
php_admin_value[open_basedir] = /var/www/html:/tmp
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen

Caching dengan OPcache #

; /etc/php/8.3/fpm/conf.d/10-opcache.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60    ; Production: 60, Development: 0
opcache.fast_shutdown=1
opcache.enable_cli=0
# Verifikasi OPcache aktif
php -r "var_dump(function_exists('opcache_get_status'));"
# Harus output: bool(true)

Monitoring PHP-FPM #

# Status PHP-FPM pool
# Aktifkan pm.status_path di pool.d/www.conf:
# pm.status_path = /fpm-status

curl http://localhost/fpm-status
# Output: pool info, process manager stats, slow request count

# Cek error log FPM
sudo tail -f /var/log/php8.3-fpm.log

# Lihat proses PHP-FPM yang berjalan
ps aux | grep php-fpm | grep -v grep

# Slow log — query yang memakan waktu > N detik
# slowlog = /var/log/php8.3-fpm/slow.log
# request_slowlog_timeout = 5s

Ringkasan #

  • Direktif php_fastcgi unix//run/php/php8.3-fpm.sock adalah semua yang dibutuhkan untuk PHP dasar — jauh lebih simple dari konfigurasi Nginx+PHP.
  • Selalu blokir akses ke file sensitif (.env, .git, wp-config.php) sebelum deploy ke production.
  • Gunakan Unix socket (unix//run/php/php8.3-fpm.sock) bukan TCP untuk performa lebih baik pada server yang sama.
  • OPcache wajib diaktifkan di production — bisa meningkatkan performa PHP 3-5x dengan meng-cache bytecode.
  • Untuk WordPress dan Laravel, gunakan try_files {path} {path}/ /index.php?{query} untuk mendukung URL rewriting.
  • Bind PHP-FPM hanya ke socket atau localhost — jangan expose port PHP-FPM ke internet karena tidak ada autentikasi.

← Sebelumnya: Node.js App   Berikutnya: Python WSGI →


PHP dengan Redis Session #

# Install PHP Redis extension
sudo apt install php8.3-redis

# Konfigurasi session di Redis
; /etc/php/8.3/fpm/conf.d/redis-session.ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?auth=your-redis-password"
session.gc_maxlifetime = 7200

Menggunakan Redis untuk session memungkinkan multiple server PHP-FPM berbagi session — penting untuk horizontal scaling di mana beberapa server menjalankan instance PHP yang sama.


Magento / E-commerce PHP #

shop.example.com {
    root * /var/www/magento/pub
    
    encode gzip zstd
    
    # Magento security
    @blocked {
        path /app/*
        path /var/*
        path /lib/*
        path /dev/*
        path /phpunit.xml
        path /.git*
        path /composer.*
    }
    respond @blocked 403
    
    # Magento front controller
    php_fastcgi unix//run/php/php8.2-fpm.sock {
        # Magento butuh timeout lebih panjang (report generation, dll.)
        read_timeout 300s
    }
    
    file_server
    
    # Magento URL rewriting
    try_files {path} {path}/ /index.php?{query}
}

PHP Debugging di Development #

# Development: nonaktifkan cache dan aktifkan error detail
localhost:8080 {
    root * /var/www/myapp
    
    # Matikan HTTPS di development
    # (Caddy di localhost otomatis pakai self-signed cert)
    
    php_fastcgi unix//run/php/php8.3-fpm.sock {
        env PHP_XDEBUG_MODE debug
        env PHP_XDEBUG_CLIENT_HOST host.docker.internal
    }
    
    file_server
    
    try_files {path} {path}/ /index.php?{query}
}
; /etc/php/8.3/fpm/conf.d/xdebug.ini (development only!)
zend_extension=xdebug
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9003

Tuning PHP-FPM untuk Caddy #

Caddy sangat efisien dalam menangani koneksi ke PHP-FPM. Beberapa tips tuning:

# Cek berapa worker PHP-FPM yang aktif saat ini
ps aux | grep "php-fpm: pool www" | grep -v grep | wc -l

# Monitor PHP-FPM pool status secara real-time
watch -n 2 'curl -s http://localhost/fpm-status | grep -E "(idle|active|total)"'

# Hitung kebutuhan memory per worker
# Cek usage memory PHP-FPM process:
ps -eo pid,pmem,rss,comm | grep php-fpm | awk '{print $3}' | \
    awk 'BEGIN{s=0}{s+=$1}END{print s/1024 " MB total, " NR " workers, " s/NR/1024 " MB avg"}'

Gunakan hasil perhitungan ini untuk mengkonfigurasi pm.max_children secara tepat. Aturan praktis: pm.max_children = (RAM tersedia untuk PHP) / (rata-rata memory per worker).

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact