# Isolar pools PHP-FPM por site

> Isolar pools PHP-FPM por site: verificar pools existentes, proteger sockets, limitar extensões, ocultar páginas de estado e definir limites para cada pool.

Fonte: https://phpsos.de/pt/blog/php-fpm-pools-isolieren/  
Atualizado em: 25/10/2026  
Prestador: PHP SOS, Assistência de emergência PHP e segurança de servidores. Ajuda imediata por WhatsApp: https://wa.me/491736494914?text=Ol%C3%A1%2C%20PHP%20SOS%2C%20precisamos%20de%20ajuda%20com%20o%20nosso%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Site%3A%20%E2%80%A6

**Em resumo:** Cada site num servidor deve ter um pool PHP-FPM próprio, com utilizador de sistema próprio e socket próprio. A separação só se torna eficaz com os pormenores: permissões do socket apenas para o servidor web, `security.limit_extensions` em `.php`, nenhuma página de estado acessível publicamente, limites próprios para processos e tempo de execução e registos separados. Contra o PHP2Shell em si, só protege a atualização; os pools limitam até onde chega um ataque.

## Um servidor, muitos sites, um risco partilhado

Em muitos servidores cresceu ao longo dos anos aquilo que ninguém planeou assim. O site da empresa, a loja, uma página de campanha de 2019 e um sistema de teste correm lado a lado, muitas vezes sob o mesmo utilizador e no mesmo pool. Se a página de campanha esquecida for comprometida, os dados dos clientes da loja ficam também expostos.

O PHP-FPM, o gestor de processos FastCGI do PHP, resolve isto com pools: grupos de processos worker com definições próprias. O princípio básico é explicado em [PHP-FPM explicado: gestor de processos, pools e workers](https://phpsos.de/pt/php/php-fpm-erklaert/). A criação de pools separados, com utilizador próprio, pasta temporária própria e `open_basedir`, é descrita no guia [open_basedir e isolamento por site](https://phpsos.de/pt/ratgeber/open-basedir/). Este artigo dá um passo adicional: como verificar os pools existentes e que definições tornam a separação fiável?

Importante para o enquadramento: no PHP2Shell, as vulnerabilidades CVE-2026-109618 e CVE-2026-109619 estão no interpretador PHP, que todos os pools de uma versão do PHP partilham. Um pool próprio não impede a exploração. Mas decide se um atacante chega depois a um site ou a todos.

## Pools PHP-FPM com utilizador próprio: verificar o existente

Antes de alterar seja o que for, obtenha uma visão geral. Os comandos seguintes apenas leem. Os caminhos e os números de versão variam consoante a distribuição:

```bash
# Todos os pools com utilizador e socket
grep -HE '^\s*(\[|user|group|listen)\s*' /etc/php/*/fpm/pool.d/*.conf

# Pools em execução e respetivos utilizadores
ps -eo user,pid,cmd | grep '[p]hp-fpm: pool'

# Sockets e respetivas permissões
ls -l /run/php/

# Verificar erros na configuração (não altera nada)
sudo php-fpm8.3 -t
```

Atenção a três padrões: vários sites no mesmo pool, pools que correm como `www-data` ou até como `root`, e sockets com permissão de escrita para todos os utilizadores. Qualquer um deles mina a separação.

Se no servidor correrem várias versões do PHP, cada uma tem o seu próprio serviço FPM, com diretórios de pools próprios. Verifique todas, não apenas a versão que configurou por último. Precisamente as versões antigas com pools esquecidos são um risco, porque muitas vezes não são mantidas nem reiniciadas após atualizações. Encontra indicações em [Várias versões do PHP num servidor](https://phpsos.de/pt/blog/mehrere-php-versionen-server/). Registe o resultado numa pequena tabela: site, pool, utilizador, socket, versão do PHP. Este quadro é, ao mesmo tempo, a base de qualquer alteração posterior.

## As definições mais importantes por pool

O quadro seguinte baseia-se na configuração do FPM no manual do PHP. Os valores para processos e tempos dependem da sua carga e aplicação:

| Definição | Finalidade | Recomendação |
|---|---|---|
| `user`, `group` | utilizador dos workers | utilizador próprio por site, nunca `root` |
| `listen.owner`, `listen.group`, `listen.mode` | permissões do socket | apenas o grupo do servidor web, modo `0660` |
| `listen.acl_users` | acesso por ACL em vez de proprietário | registar apenas o utilizador do servidor web |
| `security.limit_extensions` | extensões executáveis | limitar a `.php` (por defeito `.php .phar`) |
| `clear_env` | esvaziar variáveis de ambiente | manter o valor por defeito `yes` |
| `pm.max_children` | número máximo de workers | limitar de modo que um site não esgote o servidor |
| `request_terminate_timeout` | interrupção de pedidos bloqueados | definir de acordo com o pedido legítimo mais longo |
| `pm.status_path`, `ping.path` | página de estado e de ping | definir só se for necessário e proteger internamente |
| `slowlog`, `request_slowlog_timeout` | registo de pedidos lentos | um ficheiro próprio por pool |

Um excerto para um pool reforçado tem este aspeto:

```ini
; /etc/php/8.3/fpm/pool.d/shop.conf (excerto)
[shop]
user = shop
group = shop
listen = /run/php/shop.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
request_terminate_timeout = 60s

security.limit_extensions = .php
clear_env = yes

slowlog = /var/log/php/shop.slow.log
request_slowlog_timeout = 10s
php_admin_value[error_log] = /var/log/php/shop.error.log
```

Definições como `memory_limit` ou `session.upload_progress.enabled` fixam-se por pool com `php_admin_value` e `php_admin_flag`. Segundo o manual, estes valores não podem ser substituídos com `ini_set()`. Mais informação em [php_admin_value: bloquear definições contra a sobrescrita](https://phpsos.de/pt/blog/php-admin-value-sperren/).

## Classificar corretamente as páginas de estado e a rotação de workers

`pm.status_path` e `ping.path` só estão ativos se estiverem definidos. A página de estado mostra pedidos em curso, processos e carga. Para a monitorização é útil, mas, se for acessível publicamente, é uma fonte de informação desnecessária para os atacantes. Encaminhe estes caminhos no servidor web apenas para endereços internos. Como o Nginx e o PHP-FPM colaboram em segurança é descrito em [Proteger o Nginx com PHP-FPM](https://phpsos.de/pt/server/nginx-php-fpm/).

`pm.max_requests` define após quantos pedidos um worker é reiniciado; o valor por defeito é `0`, ou seja, nunca. Um valor superior a zero ajuda contra um consumo de memória que cresce lentamente. Como proteção contra o PHP2Shell não está pensado: o php.net não o menciona entre as medidas transitórias e sublinha que só a atualização protege por completo. Após a atualização, vale ainda: todos os workers de todos os pools têm de ser reiniciados, porque os processos antigos continuam, caso contrário, a correr com o código vulnerável.

> **Dica:**
> Mantenha um modelo para novos pools e crie com ele cada novo site. Assim, a separação surge automaticamente, em vez de ser acrescentada anos mais tarde.

## Erros típicos na migração

O erro mais frequente é um novo pool que corre sob um utilizador próprio, mas cujos ficheiros continuam a pertencer a `www-data`. Então o pool não pode escrever onde precisa e alguém define as permissões de forma demasiado generosa. Esclareça antes que pastas têm de permitir escrita. O segundo erro são as tarefas agendadas que continuam a correr sob o utilizador antigo e criam ficheiros com o proprietário errado. O terceiro é uma pasta de sessões partilhada por todos os pools, que volta a anular a separação.

Depois de cada migração, teste o início de sessão, os uploads, as caches e as tarefas agendadas do site e observe o registo de erros do pool.

## Como ajuda concretamente a PHP SOS?

- Registamos todos os pools, utilizadores, sockets e definições e mostramos onde os sites partilham hoje processos ou permissões.
- Configuramos para cada site um pool reforçado, com permissões do socket, limite de extensões, limites de recursos e registos próprios.
- Protegemos as páginas de estado, reiniciamos todos os workers de forma controlada e testamos cada site.
- No âmbito do [reforço de segurança de servidores](https://phpsos.de/pt/leistungen/server-haertung/), documentamos a separação como modelo para projetos futuros.


## Perguntas frequentes

**Porque deve cada site ter um pool PHP-FPM próprio?**  
Um pool próprio com utilizador de sistema próprio separa os sites ao nível dos processos e das permissões de ficheiros. Se um site for comprometido, o código não consegue, sem mais, ler os ficheiros dos outros. Além disso, os limites e as definições podem ser fixados separadamente para cada site.

**Um pool próprio protege contra o PHP2Shell?**  
Não. As vulnerabilidades estão no próprio interpretador PHP, que todos os pools partilham. Só a atualização para uma versão corrigida, com reinício de todos os workers, protege. Pools separados limitam, no entanto, até onde chega um ataque bem-sucedido.

**O que faz o security.limit_extensions?**  
Segundo o manual do PHP, a definição limita as extensões de ficheiro que o PHP-FPM executa como script principal. Por defeito são .php e .phar. Limitá-las a .php impede que, por exemplo, ficheiros de imagem carregados sejam executados como PHP, caso o servidor web esteja mal configurado.

**A página de estado do PHP-FPM é perigosa?**  
Revela detalhes sobre processos e pedidos em curso. Se estiver acessível publicamente sem proteção, facilita a orientação dos atacantes. Segundo o manual, só está ativa se pm.status_path estiver definido. Nesse caso, o servidor web deve restringir o caminho a endereços internos.

## Fontes

- [Manual do PHP: configuração do FPM](https://www.php.net/manual/en/install.fpm.configuration.php)
- [Documentação do Nginx](https://nginx.org/en/docs/)
- [BSI IT-Grundschutz](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
