15%

Hemat 15% di Semua Layanan Hosting

Uji kemampuanmu dan dapatkan Diskon pada paket hosting apa saja

Gunakan kode:

Skills
Memulai
10.10.2024

PHP-FPM (FastCGI Process Manager): Panduan Lengkap Pengaturan, Konfigurasi, dan Optimasi

PHP-FPM (PHP FastCGI Process Manager) adalah manajer proses PHP alternatif berkinerja tinggi yang mengimplementasikan protokol FastCGI untuk memisahkan eksekusi PHP dari proses web server. Alih-alih menjalankan interpreter PHP baru untuk setiap permintaan HTTP yang masuk — seperti yang dilakukan CGI tradisional — PHP-FPM mempertahankan kumpulan proses worker yang persisten yang menerima, mengeksekusi, dan mengembalikan respons PHP dengan overhead yang jauh lebih rendah.

Untuk setiap web server produksi yang menjalankan WordPress, Laravel, Symfony, atau aplikasi PHP kustom, PHP-FPM adalah handler standar yang digunakan. PHP-FPM memungkinkan kontrol terperinci atas siklus hidup proses, batas memori, antrean permintaan, dan isolasi per-aplikasi — kemampuan yang sama sekali tidak tersedia dengan mod_php atau CGI biasa.

Perbedaan PHP-FPM dari CGI dan mod_php

Untuk memahami mengapa PHP-FPM penting, ada baiknya melihat dengan tepat apa yang digantikannya dan mengapa alternatif tersebut tidak memadai pada skala besar.

FiturCGImod_phpPHP-FPM
Model prosesProses baru per permintaanTertanam di ApacheKumpulan worker persisten
Efisiensi memoriSangat burukSedangSangat baik
Ketergantungan web serverEratErat (hanya Apache)Terpisah (server apa pun)
Isolasi per-situsTidak adaTidak adaPenuh (pool terpisah)
Reload gracefulTidakTidakYa
Slow log / profilingTidakTidakYa
Penskalaan proses dinamisTidakTidakYa
Dukungan Unix socketTidakTidakYa
Kompatibel dengan NGINXTidakTidakYa

CGI melakukan fork proses OS baru untuk setiap permintaan. Pada lalu lintas sedang, ini menciptakan ribuan siklus fork/exec/exit per menit, yang menghabiskan CPU dan memori. mod_php menyematkan interpreter PHP langsung ke setiap worker Apache, artinya setiap proses Apache — bahkan yang melayani gambar statis — membawa runtime PHP penuh di memori. PHP-FPM menyelesaikan kedua masalah tersebut: worker bersifat persisten dan sepenuhnya terpisah dari web server, sehingga NGINX atau Apache menangani aset statis secara native sementara PHP-FPM hanya menangani eksekusi PHP.

Arsitektur PHP-FPM: Alur Permintaan Secara Detail

Memahami jalur permintaan internal sangat penting untuk penyetelan dan debugging.

  1. Browser mengirimkan permintaan HTTP untuk sumber daya .php.
  2. Web server (NGINX atau Apache) menerima permintaan dan mencocokkannya dengan blok lokasi atau direktif FilesMatch.
  3. Web server meneruskan permintaan ke PHP-FPM melalui protokol FastCGI — baik melalui Unix domain socket (/run/php/php8.2-fpm.sock) atau TCP socket (127.0.0.1:9000).
  4. Proses master PHP-FPM merutekan permintaan ke worker yang tersedia dari pool yang dikonfigurasi.
  5. Worker mengeksekusi skrip PHP, menulis ke stdout, dan mengembalikan respons ke web server.
  6. Web server mengirimkan HTML yang telah dirender ke klien.
  7. Proses worker tidak keluar — ia kembali ke pool idle, siap untuk permintaan berikutnya.

Unix socket lebih disukai daripada TCP untuk komunikasi lokal karena sepenuhnya melewati tumpukan TCP/IP, mengurangi latensi sebesar 10–20% dalam benchmark dan menghilangkan overhead binding port dan routing loopback.

Mode Manajemen Proses

PHP-FPM mendukung tiga mode pm (manajer proses), dan memilih yang salah adalah salah satu kesalahan konfigurasi yang paling umum.

pm = static

Jumlah worker yang tetap selalu berjalan, terlepas dari lalu lintas. Gunakan ini pada server khusus di mana Anda menginginkan memori yang dapat diprediksi dan dialokasikan sebelumnya serta mampu menanggung overhead idle.

pm = static
pm.max_children = 20

pm = dynamic

PHP-FPM memulai sejumlah worker dasar dan melakukan scale up atau down dalam batas yang ditentukan. Ini adalah mode yang paling umum digunakan dan default yang tepat untuk sebagian besar lingkungan VPS Hosting.

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500

pm = ondemand

Worker hanya dijalankan ketika permintaan tiba dan dihentikan setelah pm.process_idle_timeout detik tidak aktif. Ini meminimalkan konsumsi memori idle dan ideal untuk situs dengan lalu lintas rendah atau lingkungan bersama di mana puluhan pool hidup berdampingan.

pm = ondemand
pm.max_children = 20
pm.process_idle_timeout = 10s

Jebakan kritis: ondemand menimbulkan latensi cold-start pada permintaan pertama setelah periode idle. Untuk aplikasi yang sensitif terhadap latensi, dynamic selalu menjadi pilihan yang lebih baik.

Menghitung pm.max_children dengan Benar

Di sinilah sebagian besar administrator membuat kesalahan yang merugikan. Menetapkan pm.max_children terlalu tinggi menyebabkan kehabisan memori dan OOM kill; terlalu rendah menyebabkan antrean permintaan dan error 502 saat beban tinggi.

Rumus yang benar:

pm.max_children = (Available RAM for PHP) / (Average PHP worker memory usage)

Untuk menemukan rata-rata memori worker PHP Anda:

ps --no-headers -o "rss,cmd" -C php-fpm8.2 | awk '{ sum+=$1 } END { printf "Average: %d MBn", sum/NR/1024 }'

Pada VPS dengan RAM 2 GB di mana NGINX, MySQL, dan OS mengonsumsi ~600 MB, Anda memiliki sekitar 1.400 MB untuk PHP. Jika setiap worker menggunakan ~70 MB, pm.max_children yang aman adalah 20. Jangan pernah menetapkannya berdasarkan perkiraan.

Menginstal PHP-FPM

Debian / Ubuntu

sudo apt update
sudo apt install php8.2-fpm
sudo systemctl enable php8.2-fpm
sudo systemctl start php8.2-fpm

CentOS / AlmaLinux / RHEL (dengan repositori Remi)

sudo dnf install epel-release
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo dnf module enable php:remi-8.2
sudo dnf install php-fpm
sudo systemctl enable php-fpm
sudo systemctl start php-fpm

Verifikasi layanan berjalan dan konfirmasi jalur socket:

sudo systemctl status php8.2-fpm
ls -la /run/php/

Mengonfigurasi Pool PHP-FPM

Konfigurasi utama PHP-FPM berada di /etc/php/8.2/fpm/php-fpm.conf, tetapi definisi pool individual berada di /etc/php/8.2/fpm/pool.d/. Pada sistem berbasis RHEL, file pool berada di /etc/php-fpm.d/.

Setiap pool adalah lingkungan eksekusi yang terisolasi. Menjalankan beberapa aplikasi PHP di server yang sama — misalnya, situs WordPress dan Laravel API — berarti membuat file pool terpisah dengan pengguna, jalur socket, dan batas sumber daya yang terpisah. Ini adalah arsitektur yang benar untuk pengaturan multi-tenant dan jauh lebih aman daripada berbagi satu pool.

Contoh: Konfigurasi Pool Produksi

[myapp]
user = myapp
group = myapp

; Unix socket — always prefer this over TCP for local communication
listen = /run/php/myapp-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; Process manager
pm = dynamic
pm.max_children = 30
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 1000

; Slow log — log requests taking longer than 2 seconds
slowlog = /var/log/php-fpm/myapp-slow.log
request_slowlog_timeout = 2s

; Status and ping endpoints
pm.status_path = /fpm-status
ping.path = /fpm-ping

; Environment isolation
clear_env = yes
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin

; PHP value overrides per pool
php_admin_value[error_log] = /var/log/php-fpm/myapp-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256M
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M

Direktif clear_env = yes adalah pengaturan kritis keamanan yang sering diabaikan. Tanpanya, worker PHP mewarisi semua variabel lingkungan dari proses master, yang berpotensi membocorkan data tingkat sistem yang sensitif ke dalam $_ENV aplikasi Anda.

Mengintegrasikan PHP-FPM dengan NGINX

NGINX tidak memiliki kemampuan eksekusi PHP native — ia sepenuhnya bergantung pada FastCGI untuk mendelegasikan permintaan PHP. Ini sebenarnya merupakan keunggulan arsitektur: NGINX menangani file statis dengan hampir tanpa biaya sementara PHP-FPM hanya menangani apa yang memerlukan eksekusi.

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

    # Serve static files directly, no PHP involvement
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Delegate PHP to PHP-FPM
    location ~ .php$ {
        # Security: prevent executing uploaded files as PHP
        try_files $uri =404;
        fastcgi_split_path_info ^(.+.php)(/.+)$;

        fastcgi_pass unix:/run/php/myapp-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;

        # Performance tuning
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_read_timeout 300;
    }

    # Block access to the FPM status page from public
    location ~ ^/(fpm-status|fpm-ping)$ {
        allow 127.0.0.1;
        deny all;
        fastcgi_pass unix:/run/php/myapp-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Catatan keamanan: Baris try_files $uri =404; sebelum fastcgi_pass bukan opsional. Tanpanya, NGINX akan meneruskan permintaan untuk file yang tidak ada ke PHP-FPM, memungkinkan serangan path traversal di mana penyerang mengunggah gambar yang berisi kode PHP dan mengelabui server agar mengeksekusinya.

Mengintegrasikan PHP-FPM dengan Apache

Apache memerlukan mod_proxy_fcgi untuk berkomunikasi dengan PHP-FPM. Tidak seperti mod_php, pendekatan ini memungkinkan Apache menjalankan PHP-FPM sebagai pengguna terpisah, meningkatkan isolasi.

sudo a2enmod proxy_fcgi setenvif
sudo systemctl restart apache2

Konfigurasi virtual host:

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/myapp/public

    <Directory /var/www/myapp/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    <FilesMatch ".php$">
        SetHandler "proxy:unix:/run/php/myapp-fpm.sock|fcgi://localhost/"
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/myapp-error.log
    CustomLog ${APACHE_LOG_DIR}/myapp-access.log combined
</VirtualHost>

Mengaktifkan dan Menggunakan Halaman Status PHP-FPM

Halaman status bawaan adalah salah satu alat diagnostik PHP-FPM yang paling jarang digunakan. Setelah pm.status_path dikonfigurasi dalam file pool, kueri langsung:

sudo -u www-data SCRIPT_NAME=/fpm-status SCRIPT_FILENAME=/fpm-status REQUEST_METHOD=GET cgi-fcgi -bind -connect /run/php/myapp-fpm.sock

Atau, lebih praktis, melalui curl setelah mengeksposnya di endpoint internal yang dibatasi:

curl http://127.0.0.1/fpm-status?full

Metrik utama yang perlu dipantau:

  • listen queue: Permintaan yang menunggu worker bebas. Nilai di atas 0 di bawah beban berkelanjutan berarti pm.max_children terlalu rendah.
  • active processes: Worker yang sedang mengeksekusi PHP. Jika ini secara konsisten sama dengan pm.max_children, Anda berada di kapasitas penuh.
  • slow requests: Jumlah kumulatif permintaan yang melebihi request_slowlog_timeout. Angka yang terus meningkat menunjukkan bottleneck di tingkat aplikasi.

Menggunakan Slow Log untuk Debugging Performa

Slow log menangkap stack trace PHP lengkap untuk setiap permintaan yang melebihi ambang batas yang dikonfigurasi. Ini sangat berharga untuk mengidentifikasi masalah kueri N+1, panggilan I/O yang memblokir, atau loop yang tidak efisien tanpa memerlukan profiler penuh.

slowlog = /var/log/php-fpm/myapp-slow.log
request_slowlog_timeout = 2s

Entri slow log terlihat seperti ini:

[21-Jun-2025 14:32:11]  [pool myapp] pid 18432
script_filename = /var/www/myapp/public/index.php
[0x00007f3b4c001e80] PDOStatement->execute() /var/www/myapp/vendor/laravel/framework/src/Illuminate/Database/Connection.php:338
[0x00007f3b4c001d40] runQueryCallback() /var/www/myapp/vendor/laravel/framework/src/Illuminate/Database/Connection.php:295

Ini langsung memberi tahu Anda bahwa bottleneck adalah kueri database, bukan logika PHP — mengarahkan upaya optimasi Anda dengan tepat.

PHP-FPM dengan OPcache: Pasangan yang Esensial

PHP-FPM sendiri menangani manajemen proses; OPcache menghilangkan biaya parsing dan kompilasi file sumber PHP pada setiap permintaan. Bersama-sama, keduanya membentuk tumpukan performa lengkap untuk PHP di Linux.

Aktifkan dan setel OPcache di /etc/php/8.2/fpm/php.ini atau /etc/php/8.2/fpm/conf.d/10-opcache.ini khusus:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.revalidate_freq=0
opcache.validate_timestamps=0
opcache.jit_buffer_size=128M
opcache.jit=tracing

Menetapkan validate_timestamps=0 menonaktifkan pemeriksaan modifikasi file pada setiap permintaan — peningkatan performa yang signifikan dalam produksi. Saat Anda men-deploy kode baru, picu reset cache secara eksplisit:

sudo systemctl reload php8.2-fpm

Pada VPS dengan cPanel, pengaturan OPcache sering diekspos di antarmuka konfigurasi PHP, tetapi penyetelan manual melalui file .ini selalu memberikan kontrol yang lebih halus.

Penguatan Keamanan untuk PHP-FPM

Jalankan Setiap Pool sebagai Pengguna Sistem Khusus

Jangan pernah menjalankan pool PHP-FPM sebagai root atau sebagai pengguna www-data bersama di beberapa aplikasi. Buat pengguna sistem khusus per aplikasi:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp

Kemudian tetapkan user = myapp dan group = myapp dalam konfigurasi pool. Ini memastikan bahwa aplikasi PHP yang disusupi tidak dapat membaca file milik aplikasi lain di server yang sama.

Batasi Fungsi PHP

Dalam blok php_admin_value pool, nonaktifkan fungsi yang tidak memiliki kegunaan sah dalam aplikasi web:

php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

Batasi Open Basedir

Batasi akses file PHP ke direktori aplikasi:

php_admin_value[open_basedir] = /var/www/myapp:/tmp

Gunakan Unix Socket dengan Izin Ketat

TCP socket (127.0.0.1:9000) dapat diakses oleh proses apa pun di server. Unix socket dengan listen.mode = 0660 membatasi akses hanya untuk pengguna dan grup pemilik.

Memverifikasi Tumpukan Penuh

Setelah mengonfigurasi PHP-FPM dan web server Anda, verifikasi seluruh rantai sebelum ditayangkan.

Muat ulang semua layanan:

sudo systemctl reload php8.2-fpm
sudo systemctl reload nginx
# or
sudo systemctl reload apache2

Uji sintaks konfigurasi NGINX sebelum memuat ulang:

sudo nginx -t

Buat file info sementara (hapus setelah verifikasi — file ini mengekspos data server yang sensitif):

echo "<?php phpinfo();" | sudo tee /var/www/myapp/public/phpinfo.php

Buka http://example.com/phpinfo.php di browser dan konfirmasi:

  • Server API menampilkan FPM/FastCGI
  • PHP Version sesuai dengan versi yang diinstal
  • Bagian OPcache ada dan diaktifkan

Kemudian segera hapus file tersebut:

sudo rm /var/www/myapp/public/phpinfo.php

PHP-FPM di Lingkungan Multi-Aplikasi dan Lalu Lintas Tinggi

Pada Dedicated Server yang menghosting puluhan aplikasi PHP, arsitektur multi-pool menjadi sangat penting. Setiap aplikasi mendapatkan pool-nya sendiri dengan pm.max_children yang disetel secara independen, batas memori, dan jalur slow log. Aplikasi yang bermasalah yang menghabiskan pool worker-nya tidak memengaruhi aplikasi lain.

Untuk skenario lalu lintas tinggi, kombinasikan PHP-FPM dengan:

  • NGINX FastCGI caching (fastcgi_cache) untuk melayani respons PHP yang di-cache sebagai file statis, melewati PHP-FPM sepenuhnya untuk permintaan berulang
  • Redis atau Memcached untuk penyimpanan sesi PHP, menggantikan sesi berbasis file default yang menciptakan contention I/O di bawah beban
  • Penskalaan horizontal dengan menjalankan PHP-FPM di server aplikasi di belakang load balancer, dengan NGINX di node front-end terpisah

Jika tumpukan Anda mencakup terminasi SSL, memasangkan PHP-FPM dengan SSL Certificates yang dikonfigurasi dengan benar di lapisan NGINX memastikan handshake TLS ditangani sebelum permintaan mencapai PHP-FPM, menjaga worker PHP tetap fokus secara eksklusif pada logika aplikasi.

Untuk beban kerja PHP yang intensif secara komputasi — inferensi machine learning melalui binding PHP, pemrosesan gambar, atau transcoding video — pertimbangkan GPU Hosting di mana PHP-FPM dapat mendelegasikan komputasi berat ke pustaka yang dipercepat GPU sambil mempertahankan penanganan permintaan standar untuk lapisan web.

Matriks Keputusan Utama dan Daftar Periksa Teknis

Sebelum men-deploy PHP-FPM dalam produksi, verifikasi setiap item dalam daftar periksa ini:

Pemilihan Manajer Proses

  • Gunakan pm = dynamic untuk beban kerja VPS serba guna
  • Gunakan pm = static hanya pada server khusus dengan lalu lintas yang dapat diprediksi dan berkelanjutan
  • Gunakan pm = ondemand hanya untuk pool dengan lalu lintas rendah atau pengembangan

Perencanaan Kapasitas

  • Ukur memori worker aktual dengan ps sebelum menetapkan pm.max_children
  • Sisihkan setidaknya 20% dari total RAM untuk OS, web server, dan database
  • Tetapkan pm.max_requests antara 500–1000 untuk mencegah akumulasi kebocoran memori

Keamanan

  • Setiap pool aplikasi berjalan sebagai pengguna sistem sendiri
  • clear_env = yes ditetapkan di setiap pool
  • open_basedir membatasi akses file ke direktori aplikasi
  • disable_functions memblokir fungsi eksekusi shell
  • Unix socket digunakan sebagai pengganti TCP socket

Observabilitas

  • pm.status_path dikonfigurasi dan hanya dapat diakses dari localhost
  • slowlog diaktifkan dengan request_slowlog_timeout 2–5 detik
  • Rotasi log dikonfigurasi untuk semua file log PHP-FPM

Performa

  • OPcache diaktifkan dengan validate_timestamps=0 dalam produksi
  • NGINX FastCGI caching dikonfigurasi untuk endpoint yang dapat di-cache
  • Handler sesi PHP diatur ke Redis atau Memcached, bukan file

Operasional

  • sudo systemctl reload php8.2-fpm digunakan untuk perubahan konfigurasi tanpa downtime (bukan restart)
  • phpinfo.php dihapus dari document root segera setelah verifikasi
  • Konfigurasi pool dikontrol versinya bersama kode aplikasi

FAQ

Apa perbedaan antara PHP-FPM dan mod_php?

mod_php menyematkan interpreter PHP di dalam setiap proses worker Apache, mengonsumsi memori bahkan saat melayani file statis dan mengikat PHP erat dengan Apache. PHP-FPM berjalan sebagai layanan yang sepenuhnya terpisah, berkomunikasi melalui FastCGI, bekerja dengan web server apa pun termasuk NGINX, dan memungkinkan isolasi proses per-aplikasi dengan batas sumber daya yang independen.

Bagaimana cara memilih antara Unix socket dan TCP socket untuk PHP-FPM?

Gunakan Unix socket (listen = /run/php/app-fpm.sock) setiap kali PHP-FPM dan web server berjalan di mesin fisik atau virtual yang sama. Unix socket melewati tumpukan TCP/IP, mengurangi latensi dan menghilangkan konflik port. Gunakan TCP socket (listen = 127.0.0.1:9000) hanya ketika PHP-FPM berjalan di host yang berbeda dari web server.

Mengapa saya mendapatkan error 502 Bad Gateway saat beban tinggi?

502 dari NGINX yang mengarah ke PHP-FPM hampir selalu berarti listen queue penuh — semua worker sibuk dan koneksi baru ditolak. Periksa pm.status_path untuk nilai listen queue yang bukan nol. Solusinya adalah meningkatkan pm.max_children (jika RAM memungkinkan) atau mengoptimalkan skrip PHP yang lambat yang diidentifikasi melalui slow log.

Bagaimana cara memuat ulang PHP-FPM tanpa memutus koneksi aktif?

Gunakan sudo systemctl reload php8.2-fpm daripada restart. Sinyal reload (SIGUSR2) menyebabkan proses master me-restart worker secara graceful: permintaan yang ada diselesaikan secara normal sementara worker baru mengambil konfigurasi yang diperbarui. restart yang keras menghentikan semua worker secara langsung, memutus permintaan yang sedang berjalan.

Bisakah PHP-FPM menjalankan beberapa versi PHP secara bersamaan di satu server?

Ya. Instal beberapa versi PHP (misalnya, php7.4-fpm dan php8.2-fpm) dan konfigurasikan setiap pool aplikasi untuk menggunakan jalur socket yang sesuai. Di NGINX, arahkan fastcgi_pass ke socket yang benar per blok server. Ini adalah pola standar pada infrastruktur bersama yang dikelola melalui VPS Control Panels dan sepenuhnya didukung pada VPS Hosting dengan akses root.

15%

Hemat 15% di Semua Layanan Hosting

Uji kemampuanmu dan dapatkan Diskon pada paket hosting apa saja

Gunakan kode:

Skills
Memulai