Nem todo erro 404 ou 500 em servidores web vem de código quebrado na aplicação. Recentemente, encarei um cenário de troubleshooting em que múltiplos componentes trabalhavam em camadas: Nginx na borda fazendo terminação SSL, Varnish no meio do caminho para cache, Nginx backend na porta 8080 e PHP-FPM no processamento de uma aplicação Laravel.
O sintoma inicial era a clássica mensagem:
No input file specified.
A investigação desceu da configuração do VirtualHost até o isolamento do Systemd no Linux. Aqui está o passo a passo de como isolei a causa raiz, os falsos positivos no caminho e a configuração final funcional.
1. A topologia do ambiente e o sintoma inicial#
O servidor utilizava a pilha do CloudPanel com a seguinte divisão de portas:
- Portas 80 e 443 (Nginx Edge): Fazem a terminação SSL/HTTP2 e repassam o tráfego dinâmico para o Varnish (
{{varnish_proxy_pass}}) ou entregam arquivos estáticos diretamente do disco. - Porta 8080 (Nginx Backend): Recebe o tráfego repassado internamente e faz a ponte FastCGI para o pool do PHP-FPM.
- Aplicação: Laravel, onde todas as rotas dinâmicas dependem do arquivo
/public/index.php. - Subdomínios: Dois endereços apontando para o mesmo projeto (
dev1.domain.com.brpara o frontend edev2.domain.com.brpara o dashboard).
Ao requisitar arquivos estáticos diretamente, como https://dev1.domain.com.br/robots.txt, o Nginx respondia com HTTP 200 instantaneamente. Isso confirmou que o Nginx conseguia ler o disco, mas o FastCGI falhava ao tentar repassar a execução para o PHP-FPM.
2. Isolando o problema passo a passo#
Mapeamento do document root#
A primeira checagem foi verificar o caminho físico do index.php:
cd /home/user/htdocs/domain.com.br/public_html/public
ls -la
Corrigi uma pasta duplicada comum após deploys (/public/public/), apontando o root do Nginx diretamente para /home/user/htdocs/domain.com.br/public_html/public. O erro, contudo, continuou.
Teste com script PHP puro#
Para descartar qualquer interferência de rotas do Laravel, middlewares ou variáveis no arquivo .env, criei um script isolado:
echo "<?php phpinfo();" > /home/user/htdocs/domain.com.br/public_html/public/test.php
chown user:user /home/user/htdocs/domain.com.br/public_html/public/test.php
Acessar https://dev1.domain.com.br/test.php continuava retornando "No input file specified". Ficou comprovado que a falha estava na comunicação entre o Nginx e o processo do PHP-FPM.
Identificando a porta real do pool PHP-FPM#
Ao inspecionar os serviços com journalctl -u php8.4-fpm, notei que o PHP 8.4 escutava em portas TCP internas dinâmicas (127.0.0.1:19000, 19001, 19002, 19003).
Verificando o arquivo do pool em /etc/php/8.4/fpm/pool.d/domain.com.br.conf:
[domain.com.br]
listen = 127.0.0.1:19003
user = user
group = user
pm = ondemand
O comando ss -tulpn | grep 19003 confirmou que o processo específico desse domínio rodava na porta 19003. O Nginx estava usando a variável genérica {{php_fpm_port}}, que apontava para a porta padrão 19000 (usuário clp), gerando conflito de permissão entre pools.
Ajustei o fastcgi_pass no bloco 8080 para fixar 127.0.0.1:19003.
3. O ponto de virada: o erro operation not permitted#
Ao monitorar o arquivo /var/log/nginx/error.log durante a chamada ao test.php, o log registrou a mensagem definitiva:
FastCGI sent in stderr: "Unable to open primary script: /home/user/htdocs/domain.com.br/public_html/public/test.php (Operation not permitted)" while reading response header from upstream, client: 172.x.x.x, server: dev1.domain.com.br, request: "GET /test.php HTTP/1.0", upstream: "fastcgi://127.0.0.1:19003"
No Linux, existe uma diferença fundamental entre esses dois status:
Permission denied(EACCES): Falha em permissões de arquivo tradicionais (chmod e chown).Operation not permitted(EPERM): Bloqueio por regras de segurança do Kernel, restrições de montagem ou Sandboxing do Systemd na chamada de sistemaopen().
Fiz o teste de leitura com o usuário da aplicação:
sudo -u user cat /home/user/htdocs/domain.com.br/public_html/public/test.php
A leitura funcionou sem erros. O usuário tinha acesso aos arquivos, mas o processo do PHP-FPM estava travado pelo sandbox do Systemd.
Inspecionando a árvore de diretórios e ajustando o systemd#
Analisei a árvore de permissões com o utilitário namei:
namei -om /home/user/htdocs/domain.com.br/public_html/public/test.php
O diretório /home possuía permissão 701 (drwx-----x). Combinado com a diretiva de proteção de diretórios do Systemd no Debian 12, o PHP-FPM não conseguia atravessar o caminho.
Para desativar o isolamento restritivo no Systemd, criei um override:
systemctl edit php8.4-fpm
Adicionando:
[Service]
ProtectHome=false
E recarregando o serviço:
systemctl daemon-reload
systemctl restart php8.4-fpm
4. O erro de sintaxe no Nginx: invalid number of arguments in root#
Ao testar a configuração com nginx -t, o terminal acusou:
nginx: [warn] the "listen ... http2" directive is deprecated, use the "http2" directive instead
nginx: [emerg] invalid number of arguments in "root" directive in /etc/nginx/sites-enabled/domain.com.br.conf:89
A causa foi a falta do ponto e vírgula na linha do root no bloco da porta 8080:
# Incorreto:
root /home/user/htdocs/domain.com.br/public_html/public
try_files $uri $uri/ /index.php?$args;
# Correto:
root /home/user/htdocs/domain.com.br/public_html/public;
try_files $uri $uri/ /index.php?$args;
Sem o ;, o parser do Nginx interpretou try_files como um segundo argumento da diretiva root. Também atualizei a sintaxe de HTTP/2 para o formato moderno (http2 on;).
5. A configuração final do virtualhost#
Abaixo está o arquivo do Nginx consolidado, tratando o redirecionamento dos domínios secundários, repassando o tráfego ao Varnish e encaminhando o FastCGI diretamente para o pool na porta 19003:
# BLOCO 1: Redirecionamento de Domínios Secundários e Base
server {
listen 80;
listen [::]:80;
listen 443 quic;
listen 443 ssl;
listen [::]:443 quic;
listen [::]:443 ssl;
http2 on;
{{ssl_certificate_key}}
{{ssl_certificate}}
server_name www.domain.com.br domain.com.br dev2.domain.com.br;
return 301 https://dev1.domain.com.br$request_uri;
}
# BLOCO 2: Proxy Reverso, SSL Termination e Arquivos Estáticos
server {
listen 80;
listen [::]:80;
listen 443 quic;
listen 443 ssl;
listen [::]:443 quic;
listen [::]:443 ssl;
http2 on;
http3 off;
{{ssl_certificate_key}}
{{ssl_certificate}}
server_name dev1.domain.com.br;
root /home/user/htdocs/domain.com.br/public_html/public;
{{nginx_access_log}}
{{nginx_error_log}}
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
location ~ /.well-known {
auth_basic off;
allow all;
}
{{settings}}
include /etc/nginx/global_settings;
location / {
{{varnish_proxy_pass}}
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header X-Varnish;
proxy_redirect off;
proxy_max_temp_file_size 0;
proxy_connect_timeout 720;
proxy_send_timeout 720;
proxy_read_timeout 720;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}
location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|woff2|eot|mp4|ogg|ogv|webm|webp|zip|swf|map)$ {
add_header Access-Control-Allow-Origin "*";
add_header alt-svc 'h3=":443"; ma=86400';
expires max;
access_log off;
}
}
# BLOCO 3: Backend Interno (Nginx para FastCGI PHP-FPM)
server {
listen 8080;
listen [::]:8080;
server_name dev1.domain.com.br;
root /home/user/htdocs/domain.com.br/public_html/public;
try_files $uri $uri/ /index.php?$args;
index index.php index.html;
location ~ \.php$ {
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files $uri =404;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
fastcgi_param HTTPS "on";
fastcgi_param SERVER_PORT 443;
fastcgi_pass 127.0.0.1:19003;
fastcgi_param PHP_VALUE "{{php_settings}}";
}
location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|woff2|eot|mp4|ogg|ogv|webm|webp|zip|swf|map)$ {
add_header Access-Control-Allow-Origin "*";
expires max;
access_log off;
}
}
Principais lições do troubleshooting#
No input file specifiednem sempre é caminho errado: O erro ocorre tanto quando o$document_rootestá incorreto quanto quando o PHP-FPM não tem permissão para abrir o arquivo devido a bloqueios do Systemd.Operation not permittedindica sandbox: Se o usuário do sistema lê o arquivo normalmente via terminal mas o serviço web falha comEPERM, verifique oProtectHomeno Systemd e políticas de segurança.- Descubra a porta real do pool: Em ambientes com múltiplos pools PHP, nunca presuma a porta padrão. Confira o arquivo em
/etc/php/X.Y/fpm/pool.d/e valide comss -tulpn. - Cuidado com pontos e vírgulas no Nginx: Uma linha sem
;faz o parser engolir a diretiva seguinte como parâmetro extra, gerando erros crípticos nonginx -t.
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários