Cos’è PHP-FPM | Installare e configurare PHP-FPM

Ambiente di test Famiglia RHELAlmaLinux 9.8Apache 2.4 + PHP-FPM 8.3account rootVerificato il 2026-10-26

PHP-FPM è un gestore di processi FastCGI in cui processi worker avviati in anticipo ricevono le richieste PHP che un server web gli passa e le elaborano. Su un server AlmaLinux 9 con Apache, questa guida verifica se è installato e come sono impostati i pool e i socket di ciascun sito, e arriva fino al test della configurazione e al controllo dello stato con l'output reale.

Apache può anche eseguire PHP direttamente con mod_php, ma se lo affidi a PHP-FPM, server web e PHP restano separati. Nginx non può eseguire PHP direttamente, quindi passa le richieste a un processo FastCGI come PHP-FPM. Per questo un solo PHP-FPM si può collegare sia ad Apache sia a Nginx. Le impostazioni dei pool e la struttura dei socket più sotto valgono così come sono anche quando colleghi PHP-FPM a Nginx.

1️⃣ Cos'è PHP-FPM: la differenza tra CGI e FastCGI

CGI (Common Gateway Interface) è il metodo standard con cui un server web esegue un programma esterno per generare contenuti dinamici, e avvia di nuovo il programma a ogni richiesta in arrivo. Il costo di creare e rimuovere un processo per ogni richiesta si accumula, e più gli accessi aumentano, più il server risponde lentamente.

FastCGI elimina questo costo avviando il programma in anticipo ed elaborando le richieste una dopo l'altra. È la differenza tra accendere e spegnere il computer a ogni utilizzo e usare subito un computer già acceso. PHP-FPM (FastCGI Process Manager) è il gestore che esegue PHP tramite FastCGI ed è incluso in PHP dalla versione 5.3.3.

Per ogni pool, cioè un gruppo di worker, PHP-FPM avvia in anticipo il numero di worker stabilito; un worker libero riceve la richiesta che il server web passa attraverso il socket, la elabora e aspetta la successiva. I file statici come immagini e CSS sono serviti direttamente dal server web, e solo i file PHP passano a PHP-FPM. Cambia soltanto il modo in cui il server web passa le richieste al socket: Apache usa il modulo mod_proxy_fcgi e Nginx usa la direttiva fastcgi_pass.

🧩 Come CGI e PHP-FPM elaborano le richieste
Diagramma esplicativo
⚙️ Esecuzione di PHP
🌐 Server web
🌐 ApacheNginx
📨 Richiesta 1 · index.php📨 Richiesta 2 · wp-login.php📨 Richiesta 3 · index.php
I file statici (immagini, CSS) sono serviti direttamente dal server web
Eseguito a ogni richiestaFastCGI · socket→
🧱 Processi CGI
Richiesta 1Nuovo processo → elaborazione → chiusura
Richiesta 2Nuovo processo → elaborazione → chiusura
Richiesta 3Nuovo processo → elaborazione → chiusura
Quando l'elaborazione finisce, sparisce anche il processo · la richiesta successiva riparte da capo
🧰 Pool PHP-FPM [siteuser]
Worker 1Richiesta 1
Worker 2Richiesta 2
Worker 3Richiesta 3
Worker 4attesa
Worker 5attesa
I worker avviati in anticipo ricevono le richieste e, quando finiscono, aspettano la successiva
Quando Apache esegue PHP come CGI, avvia un nuovo processo PHP a ogni richiesta e lo chiude al termine dell'elaborazione, quindi il costo di creare i processi si accumula man mano che le richieste aumentano.
Nginx non ha alcun modulo che esegua direttamente programmi CGI, perciò questa combinazione non si usa; PHP viene passato a PHP-FPM tramite FastCGI.
Apache passa le richieste PHP al socket con mod_proxy_fcgi, e un worker PHP-FPM avviato in anticipo la riceve, la elabora e aspetta la successiva.
Nginx le passa allo stesso socket con fastcgi_pass, quindi anche con un server web diverso il pool PHP-FPM resta lo stesso.

2️⃣ Installare PHP-FPM: controllare il pacchetto e installare con dnf

Se hai installato PHP con dnf su un server della famiglia RHEL, il pacchetto php-fpm è stato installato insieme. Controlla prima con rpm se è installato. Il processo di installazione di PHP è lo stesso di Installare APM su Rocky Linux.

rpm -qa | grep php-fpm
php-fpm-8.3.36-1.module_php.8.3.el9.remi.x86_64

Se l'output è vuoto, non è installato; installalo con dnf.

dnf -y install php-fpm

Quando l'installazione finisce, riesegui lo stesso comando rpm per verificare che venga mostrato il nome del pacchetto.

3️⃣ Configurare PHP-FPM: il pool www.conf, il socket e le modalità statica e dinamica

I file di configurazione sono due: la configurazione generale [/etc/php-fpm.conf] e la configurazione dei pool [/etc/php-fpm.d/www.conf]. Le righe da guardare per prime nel pool predefinito www.conf sono listen e pm, e i valori subito dopo l'installazione sono questi.

grep -E '^(listen|pm) ' /etc/php-fpm.d/www.conf
listen = /run/php-fpm/www.sock
pm = dynamic

listen è il punto in cui il server web passa le richieste, e il valore predefinito della versione 8.3 è il socket Unix [/run/php-fpm/www.sock]. Il valore predefinito delle versioni vecchie, [127.0.0.1:9000], riceve le richieste su una porta TCP. All'interno dello stesso server il socket è più leggero perché salta la procedura di connessione tramite porta, e con listen.owner e listen.group puoi limitare l'accesso come con i permessi dei file.

🔲 Impostare la modalità statica e dinamica

pm è il modo in cui si avviano i worker, e lo imposti su uno tra static, dynamic e ondemand. La modalità statica tiene sempre avviato il numero scritto in pm.max_children, e l'impostazione qui sotto mantiene 100 worker.

pm = static
pm.max_children = 100

La modalità dinamica è quella predefinita e fa salire o scendere il numero di worker in base al volume di richieste. L'impostazione qui sotto ne avvia 12 all'inizio, mantiene tra 6 e 18 worker liberi e arriva a un massimo di 120.

pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18

La modalità ondemand avvia i worker solo quando arriva una richiesta e li chiude dopo che è trascorso pm.process_idle_timeout; per questo va bene per i siti con pochi accessi e non per quelli con molti accessi.

Le tre modalità si distinguono per il momento in cui avviano i worker e per il modo in cui il loro numero sale e scende.

ModalitàCome vengono avviati i workerSiti adatti
static (statico)Tiene sempre avviato il numero scritto in pm.max_childrenSiti con molti accessi
dynamic (dinamico)Predefinito · sale e scende entro pm.start_servers, pm.min_spare_servers e pm.max_spare_servers in base al volume di richiesteSiti con accessi che salgono e scendono
ondemandAvvia solo quando arriva una richiesta e chiude dopo che è trascorso pm.process_idle_timeoutSiti con pochi accessi

max_children si stabilisce dividendo la memoria del server per la memoria usata da un worker. Anche quando si accumulano gli avvisi su [max_children], non alzarlo subito; prima individua nei log quali richieste hanno riempito i worker.

La memoria e il limite di upload si impostano in php.ini, la configurazione generale di PHP, e si regolano insieme al numero di worker in base al sito che gestisci.

memory_limit = 1024M
post_max_size = 128M
upload_max_filesize = 128M

I tre valori sono il limite di memoria che può usare un singolo script PHP e la dimensione dei file che si possono caricare in una volta, e si applicano solo dopo aver riavviato PHP-FPM.

🔲 Impostare un pool per account del sito

Se i siti sono più di uno, non si condivide un unico www.conf: si crea un file di pool per ogni account e si separano l'account di esecuzione e il socket. Il PHP di un sito non può leggere i file di un altro account, e il numero di worker si stabilisce sito per sito.

vi /etc/php-fpm.d/siteuser.conf

Nel file si scrivono il nome del pool, l'account di esecuzione, il percorso del socket e il numero di worker.

[siteuser]
user = siteuser
group = nobody
listen = /run/php-fpm/siteuser.sock
listen.owner = siteuser
listen.group = nobody
listen.mode = 0660
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
chdir = /home/siteuser/www

listen.owner e listen.group sono il proprietario e il gruppo del file del socket, e PHP-FPM crea il socket con questi valori all'avvio. Se il server web gira con l'account nobody, scrivi nobody in listen.group; se gira con l'account apache, scrivi apache, in modo che il server web possa aprire il socket.

listen.owner = siteuser
listen.group = nobody
listen.mode = 0660

Queste tre righe vanno in ogni file di pool, e dopo aver cambiato i valori bisogna riavviare perché il socket venga ricreato con i nuovi permessi.

🔲 Impostare slowlog

slowlog è un file che registra dove si trovava l'esecuzione delle richieste durate più di request_slowlog_timeout, e con il valore 0 non registra nulla. Quando cerchi la causa delle richieste lente, attivalo indicando un tempo in secondi, come 3s.

slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 0

Il file registrato conserva il percorso dello script della richiesta lenta e la funzione in esecuzione in quel momento, così puoi vedere quale plugin o quale codice ha richiesto tempo.

4️⃣ Integrazione con Apache: impostazioni del VirtualHost e permessi del socket

Apache passa al socket del pool le richieste dei file PHP con il modulo mod_proxy_fcgi. Inserisci una riga SetHandler nel FilesMatch dentro il VirtualHost, e per ogni sito scrivi il socket del suo account.

# Un VirtualHost per account del sito · in SetHandler va il socket di quell'account (al posto di SetHandler si può collegare anche con ProxyPassMatch)
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /home/siteuser/www

    <Directory /home/siteuser/www>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

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

DocumentRoot e Directory sono la radice web di quell'account, e -Indexes in Options impedisce che l'elenco delle cartelle venga mostrato nel browser.

🔲 Impostare i permessi del socket

Quando il pool parte, il socket viene creato con i valori di listen.owner, listen.group e listen.mode, e con ls controlli che i permessi siano corretti.

ls -l /run/php-fpm/
totale 4
srw-rw----  1 siteuser_a nobody 0 ott 22 23:34 siteuser_a.sock
-rw-r--r--  1 root       root   7 ott 26 03:00 php-fpm.pid
srw-rw----  1 siteuser_b nobody 0 ott 22 23:34 siteuser_b.sock
srw-rw----+ 1 root       root   0 ott 22 23:34 www.sock

Se i permessi non coincidono e il server web non riesce ad aprire il socket, i visitatori ricevono un errore 503; per correggere subito senza riavviare, imposta proprietario e permessi con chown e chmod.

Questa è la sintassi attuale, che separa utente e gruppo con i due punti.

chown siteuser:nobody /run/php-fpm/siteuser.sock

Dopo aver cambiato il proprietario, imposta i permessi a 660.

chmod 660 /run/php-fpm/siteuser.sock

Questa è la sintassi vecchia, che separa utente e gruppo con un punto, e chown la esegue ancora così com'è su AlmaLinux 9.

chown siteuser.nobody /run/php-fpm/siteuser.sock

Dopo aver cambiato il proprietario, imposta i permessi a 660.

chmod 660 /run/php-fpm/siteuser.sock

Il risultato delle due sintassi è lo stesso: qualunque usi, il proprietario del socket diventa siteuser e il gruppo diventa nobody.

🔲 Integrazione con Nginx: la direttiva fastcgi_pass

In Nginx, il location per i file PHP dentro il blocco server passa le richieste al socket dello stesso pool con fastcgi_pass.

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/run/php-fpm/siteuser.sock;
}

Se Nginx gira con l'account nginx, nel file del pool bisogna scrivere nginx in listen.group perché possa aprire il socket.

5️⃣ Test della configurazione e riavvio: php-fpm -t e systemctl

Dopo aver cambiato la configurazione, non riavviare subito; fai prima un controllo della sintassi con php-fpm -t. Se in un file di pool c'è un refuso, al riavvio cade tutto PHP-FPM e tutti i siti ricevono un 503.

php-fpm -t
[26-Oct-2026 17:33:45] NOTICE: configuration file /etc/php-fpm.conf test is successful

Se il controllo va a buon fine, viene mostrato il messaggio [test is successful] insieme al percorso del file di configurazione, e poi applichi la modifica a PHP-FPM. Una modifica che richiede di ricreare il socket, come il percorso del socket o listen.owner, si applica con restart. Se su un server in produzione hai cambiato solo valori come il numero di worker, applicala con reload.

systemctl restart php-fpm

Se hai modificato il VirtualHost, riavvia anche Apache.

systemctl restart httpd

Registralo con enable perché venga eseguito automaticamente quando il server viene riacceso.

systemctl enable php-fpm

Controlla se è registrato con is-enabled.

systemctl is-enabled php-fpm
enabled

Con status controlla che per ogni pool ci siano worker in esecuzione.

systemctl status php-fpm
● php-fpm.service - The PHP FastCGI Process Manager
     Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; preset: disabled)
     Active: active (running) since x
    Process: 3934033 ExecReload=/bin/kill -USR2 $MAINPID (code=exited, status=0/SUCCESS)
   Main PID: 1333314 (php-fpm)
     Status: "Processes active: 4, idle: 21, Requests: x, slow: 0, Traffic: x"
      Tasks: x
     Memory: x
        CPU: x
     CGroup: /system.slice/php-fpm.service
             ├─  41920 "php-fpm: pool siteuser_a"
             ├─  94143 "php-fpm: pool siteuser_b"
             ├─1333314 "php-fpm: master process (/etc/php-fpm.conf)"
             ├─3934078 "php-fpm: pool www"
             └─4009016 "php-fpm: pool siteuser_a"

ott 26 03:00:01 server.example.com systemd[1]: Reloading The PHP FastCGI Process Manager...
ott 26 03:00:01 server.example.com systemd[1]: Reloaded The PHP FastCGI Process Manager.

Nella riga Status, active e idle sono i worker che stanno elaborando richieste in questo momento e quelli liberi, e CGroup elenca i worker per nome del pool. Il nome host e i nomi dei pool nell'output sono stati sostituiti con valori di esempio.

🔢 FAQ & contenuti consigliati

mod_php esegue PHP dentro il processo di Apache, quindi la configurazione è semplice, ma PHP viene caricato in ogni worker di Apache, il che consuma molta memoria e rende difficile separare l'account di esecuzione sito per sito. PHP-FPM separa PHP in processi a parte, così ogni sito può avere un proprio account e un proprio numero di worker; per questo, su un server con più siti o che usa Nginx, si usa PHP-FPM.

systemctl reload php-fpm invia un segnale USR2 al processo master, che rilegge le impostazioni e sostituisce i worker. Se imposti process_control_timeout, vengono sostituiti per primi i worker che hanno terminato la richiesta in corso (secondo la documentazione ufficiale). restart abbatte tutti i worker e li rialza in una volta sola, quindi le richieste di quel momento possono interrompersi; su un server in produzione usa prima reload.

Nella famiglia RHEL il log predefinito è [/var/log/php-fpm/error.log], e lì restano gli avvisi di mancanza di worker (seems busy · max_children) e le registrazioni di avvio e arresto dei pool. Nel file che indichi per ogni pool con php_admin_value[error_log] vengono registrati a parte gli errori del codice PHP di quel sito. Il pool predefinito scrive in [/var/log/php-fpm/www-error.log].

ℹ️ Informativa sull'affiliazione
I contenuti di questo sito includono link di affiliazione. Se un visitatore acquista un prodotto o un servizio tramite uno di questi link, il sito riceve una commissione dal venditore. In questo processo l'importo pagato dall'acquirente (durante le promozioni l'importo scende↓) non aumenta. Prezzi, sconti e disponibilità indicati si riferiscono al momento della stesura e possono differire da quelli reali: prima di acquistare verifica sempre presso il venditore. I prodotti vengono scelti e valutati secondo criteri propri, e le commissioni non influiscono sull'ordine di presentazione né sul contenuto delle valutazioni.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Dimostra di essere umano: 4   +   4   =