Qué es PHP-FPM | Instalar y configurar PHP-FPM
PHP-FPM es un administrador de procesos FastCGI en el que unos procesos worker, iniciados de antemano, reciben las solicitudes PHP que les pasa un servidor web y las atienden. En un servidor AlmaLinux 9 con Apache, esta guía comprueba si está instalado y cómo se configuran los pools y los sockets de cada sitio, y llega hasta la prueba de la configuración y la comprobación del estado con la salida real.
Apache también puede ejecutar PHP directamente con mod_php, pero si se lo pasa a PHP-FPM, el servidor web y PHP quedan separados. Nginx no puede ejecutar PHP directamente, así que pasa las solicitudes a un proceso FastCGI como PHP-FPM. Por eso un solo PHP-FPM se puede conectar tanto con Apache como con Nginx. La configuración de pools y la estructura de sockets que se ven más abajo se aplican tal cual cuando conectas PHP-FPM con Nginx.
1️⃣ Qué es PHP-FPM: la diferencia entre CGI y FastCGI
CGI (Common Gateway Interface) es la forma estándar en que un servidor web ejecuta un programa externo para generar contenido dinámico, y inicia el programa de nuevo cada vez que llega una solicitud. El coste de crear y eliminar un proceso por solicitud se acumula, así que el servidor responde más lento a medida que aumentan las visitas.
FastCGI evita ese coste iniciando el programa de antemano y atendiendo las solicitudes una tras otra. Es la diferencia entre encender y apagar el ordenador cada vez que lo usas y usar directamente un ordenador que ya está encendido. PHP-FPM (FastCGI Process Manager) es el administrador que ejecuta PHP mediante FastCGI, y viene incluido en PHP desde la versión 5.3.3.
En cada pool, que es un grupo de workers, PHP-FPM inicia de antemano el número de workers que se haya fijado; un worker libre recibe la solicitud que el servidor web le pasa por el socket, la atiende y espera la siguiente. Los archivos estáticos, como imágenes y CSS, los responde directamente el servidor web, y solo los archivos PHP pasan a PHP-FPM. Lo único que cambia es cómo el servidor web pasa las solicitudes al socket: Apache usa el módulo mod_proxy_fcgi y Nginx usa la directiva fastcgi_pass.
2️⃣ Instalar PHP-FPM: comprobar el paquete e instalar con dnf
Si instalaste PHP con dnf en un servidor de la familia RHEL, el paquete php-fpm se instaló junto con él. Primero comprueba con rpm si está instalado. El proceso de instalación de PHP es el mismo que en Instalar APM en Rocky Linux.
rpm -qa | grep php-fpmphp-fpm-8.3.36-1.module_php.8.3.el9.remi.x86_64Si la salida está vacía, no está instalado; instálalo con dnf.
dnf -y install php-fpmCuando termine la instalación, vuelve a ejecutar el mismo comando rpm para comprobar que se muestra el nombre del paquete.
3️⃣ Configurar PHP-FPM: el pool www.conf, el socket y los modos estático y dinámico
Hay dos archivos de configuración: la configuración general [/etc/php-fpm.conf] y la configuración de pools [/etc/php-fpm.d/www.conf]. Las líneas que conviene mirar primero en el pool predeterminado www.conf son listen y pm, y los valores justo después de la instalación son estos.
grep -E '^(listen|pm) ' /etc/php-fpm.d/www.conflisten = /run/php-fpm/www.sock
pm = dynamiclisten es el lugar al que el servidor web pasa las solicitudes, y el valor predeterminado en la versión 8.3 es el socket Unix [/run/php-fpm/www.sock]. El valor predeterminado de las versiones antiguas, [127.0.0.1:9000], recibe las solicitudes por un puerto TCP. Dentro del mismo servidor, el socket es más ligero porque se ahorra el proceso de conexión por puerto, y con listen.owner y listen.group puedes restringir el acceso como si fueran permisos de archivo.
🔲 Configurar el modo estático y el modo dinámico
pm es la forma de iniciar los workers, y se fija en uno de estos tres valores: static, dynamic u ondemand. El modo estático mantiene siempre iniciado el número que pongas en pm.max_children, y la configuración de abajo mantiene 100 workers.
pm = static
pm.max_children = 100El modo dinámico es el predeterminado y sube o baja el número de workers según el volumen de solicitudes. La configuración de abajo inicia 12 al arrancar, mantiene entre 6 y 18 workers libres y crece hasta un máximo de 120.
pm = dynamic
pm.max_children = 120
pm.start_servers = 12
pm.min_spare_servers = 6
pm.max_spare_servers = 18El modo ondemand inicia workers solo cuando llega una solicitud y los termina cuando pasa pm.process_idle_timeout, así que va bien para sitios con pocas visitas y no para sitios con muchas.
Los tres modos se diferencian en cuándo inician los workers y en cómo suben o bajan su número.
| Modo | Cómo se inician los workers | Sitios adecuados |
|---|---|---|
| static (estático) | Mantiene siempre iniciado el número indicado en pm.max_children | Sitios con muchas visitas |
| dynamic (dinámico) | Predeterminado · sube o baja dentro de pm.start_servers, pm.min_spare_servers y pm.max_spare_servers según el volumen de solicitudes | Sitios cuyas visitas suben y bajan |
| ondemand | Los inicia solo cuando llega una solicitud y los termina cuando pasa pm.process_idle_timeout | Sitios con pocas visitas |
max_children se fija dividiendo la memoria del servidor entre la memoria que usa un worker. Aunque se acumulen avisos de que se ha alcanzado [max_children], no lo subas enseguida; primero averigua en los logs qué solicitudes llenaron los workers.
La memoria y el límite de subida se fijan en php.ini, la configuración general de PHP, y se ajustan junto con el número de workers según el sitio que administres.
memory_limit = 1024M
post_max_size = 128M
upload_max_filesize = 128MLos tres valores son el límite de memoria que puede usar un script PHP y el tamaño de los archivos que se pueden subir de una vez, y solo se aplican después de reiniciar PHP-FPM.
🔲 Configurar un pool por cuenta de sitio
Si hay varios sitios, no compartas un único www.conf: crea un archivo de pool por cuenta y separa la cuenta de ejecución y el socket. El PHP de un sitio no puede leer los archivos de otra cuenta, y el número de workers se fija para cada sitio.
vi /etc/php-fpm.d/siteuser.confEn el archivo se escriben el nombre del pool, la cuenta de ejecución, la ruta del socket y el número de workers.
[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/wwwlisten.owner y listen.group son el propietario y el grupo del archivo del socket, y PHP-FPM crea el socket con estos valores al arrancar. Si el servidor web se ejecuta con la cuenta nobody, escribe nobody en listen.group; si usa la cuenta apache, escribe apache, para que el servidor web pueda abrir el socket.
listen.owner = siteuser
listen.group = nobody
listen.mode = 0660Estas tres líneas van en cada archivo de pool, y después de cambiar los valores hay que reiniciar para que el socket se vuelva a crear con los permisos nuevos.
🔲 Configurar slowlog
slowlog es un archivo que registra en qué punto se estaba ejecutando una solicitud que tardó más que request_slowlog_timeout, y con un valor de 0 no registra nada. Cuando busques la causa de las solicitudes lentas, actívalo indicando los segundos, por ejemplo 3s.
slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 0El archivo registrado conserva la ruta del script de la solicitud lenta y la función que se estaba ejecutando en ese momento, así que puedes ver qué plugin o qué código tardó más.
4️⃣ Integración con Apache: configuración de VirtualHost y permisos del socket
Apache pasa las solicitudes de archivos PHP al socket del pool con el módulo mod_proxy_fcgi. Pones una línea SetHandler dentro de FilesMatch en el VirtualHost, y en cada sitio escribes el socket de su cuenta.
# Un VirtualHost por cuenta de sitio · en SetHandler va el socket de esa cuenta (en lugar de SetHandler también se puede conectar 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 y Directory son la raíz web de esa cuenta, y -Indexes en Options evita que el listado de carpetas se muestre en el navegador.
🔲 Configurar los permisos del socket
Al iniciar el pool se crea el socket con los valores de listen.owner, listen.group y listen.mode, y con ls compruebas que los permisos son correctos.
ls -l /run/php-fpm/total 4
srw-rw---- 1 siteuser_a nobody 0 oct 22 23:34 siteuser_a.sock
-rw-r--r-- 1 root root 7 oct 26 03:00 php-fpm.pid
srw-rw---- 1 siteuser_b nobody 0 oct 22 23:34 siteuser_b.sock
srw-rw----+ 1 root root 0 oct 22 23:34 www.sockSi los permisos no coinciden y el servidor web no puede abrir el socket, los visitantes reciben un error 503; para corregirlo enseguida sin reiniciar, indica el propietario y los permisos con chown y chmod.
Esta es la sintaxis actual, que separa el usuario y el grupo con dos puntos.
chown siteuser:nobody /run/php-fpm/siteuser.sockDespués de cambiar el propietario, ajusta los permisos a 660.
chmod 660 /run/php-fpm/siteuser.sockEsta es la sintaxis antigua, que separa el usuario y el grupo con un punto, y chown la sigue ejecutando tal cual en AlmaLinux 9.
chown siteuser.nobody /run/php-fpm/siteuser.sockDespués de cambiar el propietario, ajusta los permisos a 660.
chmod 660 /run/php-fpm/siteuser.sockEl resultado de las dos sintaxis es el mismo: uses la que uses, el propietario del socket pasa a ser siteuser y el grupo pasa a ser nobody.
🔲 Integración con Nginx: la directiva fastcgi_pass
En Nginx, el location de los archivos PHP dentro del bloque server pasa las solicitudes al socket del mismo 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;
}Si Nginx se ejecuta con la cuenta nginx, hay que escribir nginx en listen.group del archivo de pool para que pueda abrir el socket.
5️⃣ Prueba de la configuración y reinicio: php-fpm -t y systemctl
Después de cambiar la configuración, no reinicies enseguida; haz primero una comprobación de sintaxis con php-fpm -t. Si hay una errata en un archivo de pool, al reiniciar se cae todo PHP-FPM y todos los sitios reciben un 503.
php-fpm -t[26-Oct-2026 17:33:45] NOTICE: configuration file /etc/php-fpm.conf test is successfulSi la comprobación se supera, se muestra el mensaje [test is successful] junto con la ruta del archivo de configuración, y después aplicas el cambio en PHP-FPM. Los cambios que obligan a volver a crear el socket, como la ruta del socket o listen.owner, se aplican con restart. Si en un servidor en producción solo cambiaste valores como el número de workers, aplícalo con reload.
systemctl restart php-fpmSi editaste el VirtualHost, reinicia también Apache.
systemctl restart httpdRegístralo con enable para que se ejecute automáticamente cuando el servidor se vuelva a encender.
systemctl enable php-fpmComprueba si está registrado con is-enabled.
systemctl is-enabled php-fpmenabledCon status comprueba que hay workers en marcha en cada pool.
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"
oct 26 03:00:01 server.example.com systemd[1]: Reloading The PHP FastCGI Process Manager...
oct 26 03:00:01 server.example.com systemd[1]: Reloaded The PHP FastCGI Process Manager.En la línea Status, active e idle son los workers que están atendiendo solicitudes ahora mismo y los que están libres, y CGroup enumera los workers por nombre de pool. El nombre del host y los nombres de los pools de la salida se han sustituido por valores de ejemplo.
🔢 FAQ & contenido recomendado
Caché
Caché: definición y todos los campos donde se usa
Explica por campos cómo las solicitudes que aciertan en la caché no llegan nunca a un worker de PHP-FPM.
Servidor de caché
Instalar y configurar Varnish Cache en Apache y Nginx
El proceso de instalación para poner un servidor de caché delante del servidor web y reducir así las propias solicitudes PHP.
Linux
15 categorías de comandos de Linux
Una tabla que clasifica los comandos en 15 categorías, incluidos rpm, grep y systemctl, que se usan en esta guía.
ℹ️ Aviso de afiliados
El contenido de este sitio incluye enlaces de afiliado. Cuando un visitante compra un producto o servicio a través de uno de ellos, el sitio recibe una comisión del vendedor. El importe que paga el comprador(baja durante las promociones ↓)no aumenta. Los precios, descuentos y existencias publicados corresponden al momento de redacción y pueden variar, así que confírmalos con el vendedor antes de comprar. Los productos se eligen y evalúan con criterios propios, y las comisiones no influyen en el orden ni en el contenido de las reseñas.