Apache 2.4 + PHP-FPM + ProxyPassMatch

29

Eu recentemente instalei o Apache 2.4 na minha máquina local, junto com o PHP 5.4.8 usando PHP-FPM.

Tudo correu bem (depois de um tempo ...), mas ainda há um erro estranho:

Eu configurei o Apache para o PHP-FPM assim:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1
</VirtualHost>

Funciona, por exemplo, se eu chamar http://localhost/info.php , obtenho o phpinfo() correto (é apenas um arquivo de teste).

Se eu chamar um diretório, no entanto, recebo um 404 com corpo File not found. e no log de erros:

[Tue Nov 20 21:27:25.191625 2012] [proxy_fcgi:error] [pid 28997] [client ::1:57204] AH01071: Got error 'Primary script unknown\n'

Atualizar

Eu agora tentei fazer o proxy com mod_rewrite:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"

    RewriteEngine on    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P]
</VirtualHost>

Mas o problema é: ele está sempre redirecionando, porque em http://localhost/ automaticamente http://localhost/index.php é solicitado, por causa de

DirectoryIndex index.php index.html

Atualização 2

Ok, então acho que "talvez verifique se há um arquivo para dar ao proxy primeiro:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"

    RewriteEngine on    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P]
</VirtualHost>

Agora a reescrita completa não funciona mais ...

Atualização 3

Agora eu tenho esta solução:

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/Users/apfelbox/WebServer"

    RewriteEngine on    
    RewriteCond /Users/apfelbox/WebServer/%{REQUEST_FILENAME} -f
    RewriteRule ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/Users/apfelbox/WebServer/$1 [L,P]
</VirtualHost>

Primeiro, verifique se existe um arquivo para passar para o PHP-FPM (com o caminho completo e absoluto ) e, em seguida, faça a regravação.

Isso não funciona ao usar a regravação de URL em um subdiretório, mas também falha em URLs como http://localhost/index.php/test/ Então, de volta à estaca zero.

Alguma idéia?

    
por apfelbox 20.11.2012 / 21:27

11 respostas

28

Depois de horas pesquisando e lendo a documentação do Apache, eu descobri uma solução que permite usar o pool, e também permitir que a diretiva Rewrite em .htaccess funcione mesmo quando o url contiver arquivos .php.

<VirtualHost ...>

 ...

 # This is to forward all PHP to php-fpm.
 <FilesMatch \.php$>
   SetHandler "proxy:unix:/path/to/socket.sock|fcgi://unique-domain-name-string/"
 </FilesMatch>

 # Set some proxy properties (the string "unique-domain-name-string" should match
 # the one set in the FilesMatch directive.
 <Proxy fcgi://unique-domain-name-string>
   ProxySet connectiontimeout=5 timeout=240
 </Proxy>

 # If the php file doesn't exist, disable the proxy handler.
 # This will allow .htaccess rewrite rules to work and 
 # the client will see the default 404 page of Apache
 RewriteCond %{REQUEST_FILENAME} \.php$
 RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
 RewriteRule (.*) - [H=text/html]

</VirtualHost>

De acordo com a documentação do Apache, o parâmetro de proxy SetHandler requer o Apache HTTP Server 2.4.10.

Espero que esta solução também o ajude.

    
por 04.03.2015 / 14:34
9

Eu me deparei com esse problema ontem também - o Apache 2.4 saiu do Debian / experimental para o Debian / unstable , forçando-me a lidar com esse novo material; não em nossos servidores de produção, é claro;).

Depois de ler o que parecem milhões de sites, documentos do Apache, relatórios de bugs e saída de depuração no log de erros, finalmente consegui que funcionasse. Não há sem suporte para o FPM com sockets , ainda. A configuração padrão do Debian tem usado sockets já há algum tempo, então os usuários do Debian terão que mudar isso também.

Aqui está o que funciona para um site CakePHP e o PHPMyAdmin (o último precisa de alguma configuração se você estiver usando os pacotes Debian), então eu posso confirmar que mod_rewrite ainda funciona como esperado para fazer uma reescrita de URL.

Observe DirectoryIndex index.php , que pode ser a razão pela qual nenhuma das suas configurações funcionou para "pastas" (pelo menos é o que não funcionou aqui).

Eu ainda recebo File not found. para diretórios, mas somente se não houver nenhum arquivo de índice pode ser analisado. Adoraria se livrar disso também, mas não é tão crítico quanto agora.

<VirtualHost *:80>
    ServerName site.localhost

    DocumentRoot /your/site/webroot
    <Directory />
            Options FollowSymlinks
            DirectoryIndex index.php
            AllowOverride All
            Require all granted
    </Directory>

    <LocationMatch "^(.*\.php)$">
            ProxyPass fcgi://127.0.0.1:9000/your/site/webroot
    </LocationMatch>

    LogLevel debug
    ErrorLog /your/site/logs/error.log
    CustomLog /your/site/logs/access.log combined
</VirtualHost>

O vhost acima funciona perfeitamente com um .htaccess na raiz assim:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

Eu não entendo bem o que você quer dizer com URL rewriting inside a subdirectory (estou apenas reescrevendo para o index.php da raiz).

(Ah, e você terá que ter certeza que o Xdebug não está em conflito com o FPM no seu sistema, fora da caixa eles querem usar as mesmas portas.)

    
por 01.06.2013 / 11:37
2

Isso é o que eu tenho. Parece funcionar bem. Eu coloquei o Drupal em um subdiretório e seu trabalho reescreve, os índices de diretório funcionam e o PATH_INFO funciona.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} ^/((.*\.php)(/.*)?)$
RewriteCond %2 -f
RewriteRule . fcgi://127.0.0.1:9000/%1 [L,P]
RewriteOptions Inherit

Eu tentei fazer algo assim sem reescrever ("If" e tal), mas não consegui fazer nada funcionar.

EDIT: Observe que, se você implementasse isso como um provedor de hospedagem compartilhada, isso poderia ser um problema de segurança. Isso permitiria que os usuários passassem scripts PHP para um proxy fcgi arbitrário. Se você tivesse um pool separado para cada usuário, isso permitiria a elevação de ataques de privilégios.

    
por 04.11.2013 / 13:50
2

Tudo o que você precisa fazer é definir:

 ProxyErrorOverride on

E não se esqueça de definir a página do cliente por:

ErrorDocument 404 /path/to/error_page_file    
    
por 24.06.2015 / 17:07
2

Ainda outra solução (requer Apache > = 2.4.10) - Dentro do vhost:

# define worker
<Proxy "unix:/var/run/php5-fpm-wp.bbox.nuxwin.com.sock|fcgi://domain.tld" retry=0>
    ProxySet connectiontimeout=5 timeout=7200
</Proxy>

<If "%{REQUEST_FILENAME} =~ /\.php$/ && -f %{REQUEST_FILENAME}">
    SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
    SetHandler proxy:fcgi://domain.tld
</If>

Então, aqui, o manipulador fcgi para PHP será definido apenas se o arquivo existir e se o nome dele corresponder à extensão do arquivo PHP.

BTW: Para aqueles que gostariam de definir o ProxyErrorOverride como Em , saiba que essa é realmente uma má ideia. O uso desta diretiva não é isento de qualquer problema. Por exemplo, qualquer aplicativo PHP enviando código HTTP como 503 levaria a resultados inesperados. O manipulador de erro padrão estaria envolvido em todos os casos e, para aplicativos PHP que fornecem API, isso é realmente um mau comportamento.

    
por 10.12.2016 / 19:12
1

A melhor maneira de resolver isso é ativar os logs de depuração para mod_proxy e mod_rewrite e php-fpm. No apache 2.4, agora você pode ativar os registros de depuração apenas para módulos específicos. link A configuração por módulo e por diretório está disponível no Apache HTTP Server 2.3.6 e posterior

Talvez você esteja recebendo uma barra dupla nos diretórios?

Veja o que eu uso e funciona bem:

<LocationMatch ^(.*\.php)$>
  ProxyPass fcgi://127.0.0.1:9000/home/DOMAINUSER/public_html$1
</LocationMatch>
    
por 25.05.2013 / 07:39
0

Uma coisa que me ocorreu ao lidar com essa questão é que, se você usar a combinação de:

chroot = /path/to/site
chdir = /

Na configuração do pool do fpm, não passe o caminho completo para a diretiva ProxyPass .

ProxyPass fcgi://127.0.0.1:9020/$1

Mas -ONLY- se o pool nessa porta estiver chrooted.

    
por 19.02.2015 / 06:26
0

Linode tem um ótimo tutorial sobre este assunto

Basicamente você configura um manipulador para todo o servidor que irá capturar qualquer script php e passá-los para o fast-cgi.

    
por 05.04.2017 / 17:28
0

Não tenho certeza se o problema está relacionado, mas encontrei uma solução de trabalho parcial aqui:

link

O truque parece estar adicionando um? char no .htaccess RewriteRule, por exemplo, usando:

RewriteRule ^(.*)$ index.php?/$1 [L,NS]

em vez de:

RewriteRule ^(.*)$ index.php/$1 [L,NS]

A origem do problema parece ser uma mudança no mod_rewrite do Apache 2.4.25. Eu usei o nível de log do Apache trace1 para observar um "loop" que passa $ 1 para php-fpm após index.php / $ 1 ter sido passado. Os $ 1 geram o erro "AH01071: Got error 'Primary script unknown \ n" ".

Espero que este pequeno petisco ajude alguém a resolver os seus problemas.

    
por 08.10.2017 / 14:17
0

Eu também tenho o erro depois de mudar para o php-fpm + apache 2.4.6 para instâncias do drupal

mas estou usando mod de evento mpm

apenas insira

DirectoryIndex index.php funciona para mim

então minhas configurações de Vhost se parecem abaixo

<VirtualHost *:8080>
  ServerAdmin webmaster@localhost
  ServerName sever.com
  DocumentRoot /var/www/html/webroot
    ErrorLog logs/web-error_log
    CustomLog logs/web-access_log common
<IfModule mpm_event_module>
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/webroot/$1
</IfModule>
  <Directory /var/www/html/webroot>
     Options FollowSymlinks
     DirectoryIndex index.php
     AllowOverride All
     Require all granted
  </Directory>
</VirtualHost>

obrigado

não há necessidade de revisar o arquivo .htaccess padrão do drupal

    
por 24.04.2018 / 20:09
0

Eu enfrento os mesmos problemas no meu servidor (centos 7.3.16 docker). Depois de rastrear o log do php-fpm, achei falta uma biblioteca sys.  %código% então, eu reestalo o nspr, ele funciona. Se você não consegue encontrar as soluções depois de tentar qualquer método, você pode tentar isso. WARNING: [pool www] child 15081 said into stderr: "php-fpm: pool www: symbol lookup error: /lib64/libnsssysinit.so: undefined symbol: PR_GetEnvSecure"

    
por 21.06.2018 / 12:59