Em resumo: O PHP-FPM (FastCGI Process Manager) executa o PHP como serviço próprio ao lado do servidor web. Um processo mestre gere pools e cada pool inicia workers que tratam pedidos através de FastCGI. Os pools podem funcionar por site, com utilizador próprio, limites próprios e definições do PHP bloqueadas. Como os workers tratam muitos pedidos em sequência, têm de ser todos reiniciados depois de uma atualização do PHP.
O que é o PHP-FPM?
O manual do PHP descreve o FPM como a implementação FastCGI principal do PHP, com funcionalidades úteis sobretudo para sites com carga elevada. O FPM foi incluído com o PHP 5.3.3 como SAPI própria, ou seja, como modo de operação próprio. O seu nome de SAPI é fpm-fcgi.
A diferença em relação ao mod_php: o PHP não corre dentro do servidor web, mas como serviço próprio. O Nginx, o Apache ou outro servidor web passa os pedidos PHP através do protocolo FastCGI e recebe de volta a resposta pronta. Assim, o servidor web e o PHP podem ser reiniciados, configurados e protegidos de forma independente. Como o FastCGI funciona em princípio está em CGI e FastCGI.
Mestre, pools e workers: o modelo de processos
O PHP-FPM tem três níveis:
- Processo mestre: lê a configuração, abre os sockets e inicia ou termina workers. Não executa ele próprio código de aplicação.
- Pools: cada pool tem um nome, um socket ou porta próprios, um utilizador Unix próprio e definições do PHP próprias. O manual refere expressamente uid, gid, chroot, ambiente e php.ini diferentes por pool.
- Workers: processos de um pool que aceitam e executam pedidos. Um worker trata muitos pedidos em sequência antes de ser substituído.
Quantos workers correm é determinado pelo gestor de processos com a diretiva pm:
| Modo | Comportamento | Diretivas importantes |
|---|---|---|
static |
número fixo de workers | pm.max_children |
dynamic |
workers entre um limite inferior e um superior | pm.start_servers, pm.min_spare_servers, pm.max_spare_servers |
ondemand |
workers só quando necessários, removidos após inatividade | pm.process_idle_timeout (por defeito 10s) |
O pm.max_children limita, em todos os modos, o número de pedidos simultâneos. O pm.max_requests substitui um worker após um número fixo de pedidos; o valor por defeito 0 significa ilimitado.
O modo adequado depende da carga. O static mantém sempre o mesmo número de workers prontos e é indicado para aplicações com utilização uniformemente intensa e memória suficiente. O dynamic é um compromisso para a maioria dos sites. O ondemand poupa memória em servidores com muitos sites pequenos, porque pools sem visitantes não ocupam workers; em contrapartida, o primeiro pedido depois de uma pausa demora um pouco mais. Um pm.max_children demasiado alto pode levar o servidor à falta de memória nos picos de carga; um demasiado baixo provoca tempos de espera e mensagens de erro do servidor web.
Um pool com definições de base seguras
Um exemplo de um pool próprio por site, com diretivas do manual do PHP. Caminhos e valores são exemplos:
; /etc/php/8.3/fpm/pool.d/kunde-a.conf
[kunde-a]
user = kunde-a
group = kunde-a
listen = /run/php/kunde-a.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 10s
request_terminate_timeout = 60s
security.limit_extensions = .php
clear_env = yes
php_admin_value[open_basedir] = /var/www/kunde-a:/tmp
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[error_log] = /var/log/php/kunde-a.error.log
Segundo o manual, os valores definidos com php_value e php_flag podem ser alterados em tempo de execução com ini_set(), ao contrário dos valores definidos com php_admin_value e php_admin_flag. O security.limit_extensions está por defeito em .php .phar e determina que extensões de ficheiro o FPM executa como script principal. O clear_env = yes é o valor por defeito e esvazia o ambiente dos workers.
Para a monitorização existe uma página de estado através de pm.status_path e uma página de ping através de ping.path. Ambas só devem ser acessíveis internamente. O FPM regista os pedidos lentos com backtrace quando request_slowlog_timeout e slowlog estão definidos.
O manual do PHP avisa: quem consegue abrir uma ligação FastCGI ao PHP-FPM controla a configuração do pedido e pode assim executar código arbitrário. O PHP-FPM nunca pode ser acessível a partir de uma rede não fidedigna. Utilize um socket Unix ou listen.allowed_clients.
Que papel desempenha o PHP-FPM no PHP2Shell?
O PHP-FPM está entre os modos de operação afetados. O modelo de processos torna-se particularmente claro no CVE-2026-109619: o estado interno pertencente ao pedido pode persistir depois de a memória ser libertada, e um pedido posterior no mesmo worker pode usá-lo antes de ser reposto. Isto só é possível porque os workers tratam muitos pedidos em sequência.
Daqui resultam três obrigações:
- Aplicar a atualização: PHP 8.5.12, 8.4.27, 8.3.36 ou 8.2.35, ou um backport da distribuição confirmado.
- Reiniciar todos os workers: Novos ficheiros no disco nada alteram enquanto houver workers antigos em execução. Isto vale para cada versão FPM instalada e para cada pool. Os comandos estão em Reiniciar o PHP-FPM e todos os workers.
- Definir os valores transitórios como bloqueados: As medidas do php.net, como
session.upload_progress.enabled=0, pertencem ao pool através dephp_admin_valueouphp_admin_flag, não ao.user.ini.
A separação em pools não substitui uma atualização, mas limita os danos: se cada site corre com um utilizador próprio, um atacante, depois de uma intrusão, não alcança automaticamente os ficheiros dos outros. Como isto se concretiza descreve-o Isolar pools PHP-FPM por site; a integração no Nginx está em Proteger o Nginx com PHP-FPM.
Como ajuda concretamente a PHP SOS?
- Levantar os pools: Listamos todas as versões FPM, pools, utilizadores e sockets do seu servidor.
- Aplicar patches e reiniciar: Atualizamos o PHP e comprovamos, através das horas de arranque, que já não corre nenhum worker antigo.
- Separar pools: No âmbito do reforço de servidores, configuramos por site um pool com utilizador próprio e definições bloqueadas.
- Verificar a acessibilidade: Controlamos que os sockets FastCGI e as páginas de estado não são acessíveis a partir do exterior.
Perguntas frequentes
O que significa FPM?
FPM significa FastCGI Process Manager. O manual do PHP descreve-o como a implementação FastCGI principal do PHP, com funcionalidades úteis sobretudo para sites com carga elevada. Foi incluído com o PHP 5.3.3.
Qual é a diferença entre pool e worker?
Um pool é um grupo de processos worker com configuração comum: utilizador, socket, limites e definições do PHP. Um worker é um processo isolado que trata pedidos um após outro. Um servidor pode ter muitos pools, por exemplo um por site.
O PHP-FPM deve estar acessível por TCP ou por um socket Unix?
Se o servidor web corre no mesmo anfitrião, o manual do PHP recomenda um socket Unix. Com TCP, é preciso definir listen.allowed_clients, porque de outro modo qualquer endereço pode ligar-se. Segundo o manual, uma porta FastCGI acessível abertamente permite a execução de código arbitrário.
O pm.max_requests protege contra falhas como o PHP2Shell?
Não. O pm.max_requests substitui um worker após um número fixo de pedidos e ajuda sobretudo contra fugas de memória em extensões. Contra uma falha no interpretador só ajuda a atualização, seguida do reinício de todos os workers.