it-swarm.com.de

Apache 2.4 + PHP-FPM + ProxyPassMatch

Ich habe kürzlich Apache 2.4 zusammen mit PHP 5.4.8 mit PHP-FPM) auf meinem lokalen Computer installiert.

Alles verlief reibungslos (nach einer Weile ...), aber es gibt immer noch einen seltsamen Fehler:

Ich habe Apache für PHP-FPM folgendermaßen konfiguriert:

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

Es funktioniert zum Beispiel, wenn ich http://localhost/info.php Aufrufe. Ich erhalte die richtige phpinfo() (es ist nur eine Testdatei).

Wenn ich jedoch ein Verzeichnis aufrufe, erhalte ich eine 404 mit body File not found. Und im Fehlerprotokoll:

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

Aktualisieren

Ich habe jetzt versucht, das Proxy mit mod_rewrite durchzuführen:

<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>

Das Problem ist aber: Es wird immer umgeleitet, weil bei http://localhost/ Wegen automatisch http://localhost/index.php Angefordert wird

DirectoryIndex index.php index.html

Update 2

Ok, also denke ich "Überprüfen Sie vielleicht zuerst, ob es eine Datei gibt, die Sie dem Proxy geben können:

<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>

Jetzt funktioniert das komplette Umschreiben nicht mehr ...

Update 3

Jetzt habe ich diese Lösung:

<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>

Überprüfen Sie zunächst, ob eine Datei an PHP-FPM übergeben werden muss (mit dem Pfad vollständig und absolut), und führen Sie dann das Umschreiben durch.

Dies funktioniert nicht, wenn das Umschreiben von URLs in einem Unterverzeichnis verwendet wird. Außerdem schlägt dies bei URLs wie http://localhost/index.php/test/ Fehl. Kehren Sie also zu Punkt eins zurück.


Irgendwelche Ideen?

32
apfelbox

Nach stundenlangem Suchen und Lesen der Apache-Dokumentation habe ich eine Lösung gefunden, mit der der Pool verwendet werden kann und die Rewrite-Direktive in .htaccess auch dann funktioniert, wenn die URL .php-Dateien enthält.

<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>

Gemäß der Apache-Dokumentation erfordert der SetHandler-Proxy-Parameter Apache HTTP Server 2.4.10.

Ich hoffe, dass diese Lösung auch Ihnen hilft.

36
FrancescoA

Ich bin gestern auch auf dieses Problem gestoßen - Apache 2.4 ist von Debian/experimentell in Debian/unstable zwingt mich, mich mit diesem neuen Zeug zu befassen; natürlich nicht auf unseren Produktionsservern;).

Nachdem ich Millionen von Websites, Apache-Dokumenten, Fehlerberichten und Debugging-Ausgaben im Fehlerprotokoll gelesen hatte, funktionierte es endlich. Nein, es gibt keine Unterstützung für FPM mit Sockets , noch nicht. Die Standard-Debian-Konfiguration verwendet seit einiger Zeit Sockets, daher müssen auch Debian-Benutzer dies ändern.

Hier ist, was für eine CakePHP-Site und PHPMyAdmin funktioniert (letzteres benötigt eine Konfiguration, wenn Sie die Debian-Pakete verwenden), damit ich bestätigen kann, dass mod_rewrite funktioniert immer noch wie erwartet, um ausgefallene URLs neu zu schreiben.

Beachten DirectoryIndex index.php, was möglicherweise der Grund dafür ist, dass keine Ihrer Konfigurationen für "Ordner" funktioniert hat (zumindest hat das hier nicht funktioniert).

Ich bekomme immer noch File not found. für Verzeichnisse, aber nur wenn keine Indexdatei vorhanden ist, kann sie analysiert werden. Würde das auch gerne loswerden, aber es ist momentan nicht so kritisch.


<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>

Der obige vhost funktioniert perfekt mit einem .htaccess in der Wurzel wie folgt:

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

Ich verstehe nicht ganz, was du mit URL rewriting inside a subdirectory obwohl (ich schreibe nur in die index.php des Roots um).


(Oh, und Sie müssen sicherstellen, dass Xdebug nicht mit FPM auf Ihrem System in Konflikt steht. Sie möchten sofort dieselben Ports verwenden.)

11
Alex

Alles was Sie tun müssen, ist festzulegen:

 ProxyErrorOverride on

Und vergessen Sie nicht, die Kundenseite einzurichten durch:

ErrorDocument 404 /path/to/error_page_file    
4
Shiqi Zhong

Noch eine andere Lösung (erfordert Apache> = 2.4.10) - Innerhalb des 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>

Hier wird der fcgi-Handler für PHP) nur festgelegt, wenn die Datei vorhanden ist und ihr Name mit PHP Dateierweiterung) übereinstimmt.

BTW : Für diejenigen, die die Idee hätten, ProxyErrorOverride auf On zu setzen, ist zu beachten, dass dies wirklich eine schlechte Idee ist. Die Verwendung dieser Richtlinie ist nicht ohne Probleme. Zum Beispiel würde jede PHP Anwendung, die HTTP-Code wie 503 sendet, zu einem unerwarteten Ergebnis führen. Die Standardfehlerbehandlungsroutine wäre in jedem Fall beteiligt und für PHP Anwendungen, die API bereitstellen, das ist wirklich ein schlechtes Verhalten.

2
Nuxwin

Das habe ich. Es scheint in Ordnung zu funktionieren. Ich habe Drupal in ein Unterverzeichnis gestellt und seine Umschreibungen funktionieren, Verzeichnisindizes funktionieren und PATH_INFO funktioniert.

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

Ich habe versucht, so etwas ohne Umschreiben zu machen ("If" und so), aber ich konnte nichts zum Laufen bringen.

BEARBEITEN: Beachten Sie, dass dies ein Sicherheitsproblem sein kann, wenn Sie dies als Shared Hosting-Anbieter implementieren. Es würde Benutzern ermöglichen, PHP - Skripte an einen beliebigen fcgi-Proxy zu übergeben. Wenn Sie für jeden Benutzer einen separaten Pool hätten, würde dies die Erhöhung von Berechtigungsangriffen ermöglichen.

2
RockinRoel

Der beste Weg, dies zu lösen, besteht darin, Debugging-Protokolle für mod_proxy und mod_rewrite und php-fpm zu aktivieren. In Apache 2.4 können Sie jetzt Debugging-Protokolle nur für bestimmte Module aktivieren. http://httpd.Apache.org/docs/current/mod/core.html#loglevel Die Konfiguration pro Modul und pro Verzeichnis ist in Apache HTTP Server 2.3.6 und höher verfügbar

Vielleicht bekommen Sie einen doppelten Schrägstrich in Verzeichnissen?

Folgendes verwende ich und es funktioniert einwandfrei:

<LocationMatch ^(.*\.php)$>
  ProxyPass fcgi://127.0.0.1:9000/home/DOMAINUSER/public_html$1
</LocationMatch>
1
troseman

Eine Sache, auf die ich bei meinem Umgang mit diesem Problem gestoßen bin, ist, dass wenn Sie die Kombination von:

chroot = /path/to/site
chdir = /

Übergeben Sie in Ihrer fpm-Poolkonfiguration nicht den vollständigen Pfad zur Anweisung ProxyPass.

ProxyPass fcgi://127.0.0.1:9020/$1

Aber NUR, wenn der Pool an diesem Port blockiert ist.

1
thinice

Ich bin nicht sicher, ob das Problem damit zusammenhängt, aber ich habe hier eine teilweise funktionierende Lösung gefunden:

https://stackoverflow.com/questions/44054617/mod-rewrite-in-2-4-25-triggering-fcgi-primary-script-unknown-error-in-php-fpm

Der Trick scheint darin zu bestehen, ein? char in der .htaccess RewriteRule, zB mit:

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

anstatt:

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

Die Ursache des Problems scheint eine Änderung in mod_rewrite von Apache 2.4.25 zu sein. Ich habe die Apache trace1-Protokollebene verwendet, um eine "Schleife" zu beobachten, die $ 1 an php-fpm übergibt, nachdem index.php/$ 1 übergeben wurde. Die $ 1 erzeugen den Fehler "AH01071: Fehler 'Primärskript unbekannt\n'".

Hoffe, dieser kleine Leckerbissen hilft jemandem, seine Probleme zu lösen.

1
Biapy

Eine leicht modifizierte Version der Antwort von @ FrancescoA, für die kein mod_rewrite erforderlich ist

<IfModule proxy_fcgi_module>
    <FilesMatch \.php$>
       <If "-f '%{REQUEST_FILENAME}'">
           SetHandler "proxy:unix:/path/to/socket.sock|fcgi://unique-domain-name-string/"
       </If>
     </FilesMatch>

     <Proxy fcgi://unique-domain-name-string>
        ProxySet connectiontimeout=5 timeout=240
     </Proxy>
</IfModule>
1
Joyce Babu

Linode hat ein großartiges Tutorial zu diesem Thema

Grundsätzlich richten Sie einen Handler für den gesamten Server ein, der alle PHP-Skripte abfängt und an fast-cgi weitergibt.

0
styks

Ich habe die gleichen Probleme auf meinem Server (Centos 7.3.16 Docker). Nachdem ich das php-fpm-Protokoll verfolgt hatte, fand ich miss sys lib. WARNING: [pool www] child 15081 said into stderr: "php-fpm: pool www: symbol lookup error: /lib64/libnsssysinit.so: undefined symbol: PR_GetEnvSecure" dann installiere ich das nspr neu, es funktioniert. Wenn Sie die Lösungen nach dem Ausprobieren von Methoden nicht finden können, können Sie dies versuchen. yum -y install/reinstall nspr

0
lemon

Dies funktioniert mit Wordpress 5.1.1 und neuer zusammen mit PHP 7.3, FastCGI, Proxy, auch MariaDB/MySQL. Wird auf meinen Servern zweimal überprüft. Funktioniert wie a Charme.

Zuerst auf CentOS/Fedora/Red Hat

Sudo yum remove php*
Sudo yum --enablerepo=extras install epel-release
Sudo yum install php-fpm php-mysql php-Gd php-imap php-mbstring 
Sudo grep -E '(proxy.so|fcgi)' /etc/httpd/conf.modules.d/00-proxy.conf
Sudo mv /etc/httpd/conf.d/php.conf /etc/httpd/conf.d/php.conf_bak

Bearbeiten Sie diese Datei:

Sudo nano /etc/php-fpm.d/www.conf

Fügen Sie Folgendes ein:

[www]

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 127.0.0.1:9000
listen = /run/php-fcgi.sock

Sudo ll /run/php-fcgi.sock

Sollte srw-rw-rw- geben.

Oder wie man Debian/Ubuntu einrichtet

Lernprogramm:

quelle: https://emi.is/?page=articles&article=php-7-installation-and-configuration-for-Apache-2.4-using-php-fpm- (debian, -repository)


Sudo apt purge 'php*' or Sudo apt-get purge 'php*'
Sudo add-apt-repository ppa:ondrej/php
Sudo apt-get update
Sudo apt install php7.3 php7.3-fpm php-mysql php-mbstring php-Gd php-imap libapache2-mod-security2 modsecurity-crs
systemctl status php7.3-fpm
systemctl stop php7.3-fpm.service

Sudo a2dismod php7.0 php7.1 php7.2 mpm_event mpm_worker
Sudo a2enmod mpm_prefork
Sudo a2enmod php7.3
Sudo systemctl restart Apache2 (httpd in CentOS)

Das Problem ist, dass PHP 7.3 von Ondrej Repo nur mit dem Modus mpm_prefork funktioniert. Er hat Git Repo, also kannst du ihn im Netz finden und ihn fragen, ob er PHP 7.3 für mpm_worker und mpm_event machen wird. Der Rest der Konfiguration für Distributionen der Debian-Familie ist unten aufgeführt:


Sudo apt --assume-yes install php7.3-fpm
Sudo systemctl stop php7.3-fpm.service
Sudo rm /var/log/php7.0-fpm.log
Sudo mkdir /var/log/php7.3-fpm/
Sudo touch /var/log/php7.3-fpm/error.log
Sudo mkdir /var/log/php7.3/
Sudo touch /var/log/php7.3/error.log
Sudo mkdir /var/tmp/php7.3/
Sudo > /etc/php/7.3/fpm/php.ini
Sudo > /etc/php/7.3/fpm/php-fpm.conf
Sudo rm /etc/php/7.3/fpm/pool.d/www.conf
Sudo touch /etc/php/7.3/fpm/pool.d/example.com.conf
Sudo useradd --comment "PHP" --Shell "/usr/sbin/nologin" --system --user-group php

Sudo nano /etc/php/7.3/fpm/php.ini

einfügen


[PHP]
date.timezone = Europe/Prague
display_errors = Off
error_log = /var/log/php7.3/error.log
error_reporting = 32767
log_errors = On
register_argc_argv = Off
session.gc_probability = 0
short_open_tag = Off
upload_tmp_dir = /var/tmp/php7.3/

Sudo nano /etc/php/7.3/fpm/php-fpm.conf

einfügen


[global]
error_log = /var/log/php7.3-fpm/error.log
include = /etc/php/7.3/fpm/pool.d/*.conf

Sudo nano /etc/php/7.3/fpm/pool.d/example.com.conf

einfügen


[example.com]
group = php
listen = 127.0.0.1:9000
pm = ondemand
pm.max_children = 5
pm.max_requests = 200
pm.process_idle_timeout = 10s
user = php

Sudo nano /etc/logrotate.d/php7.3-fpm

kopieren Sie dies in die TXT-Datei:

/var/log/php7.3-fpm.log {
    rotate 12
    weekly
    missingok
    notifempty
    compress
    delaycompress
    postrotate
            /usr/lib/php/php7.3-fpm-reopenlogs
    endscript
}

entfernen Sie es und fügen Sie es statt oben ein:

/var/log/php7.3/*.log /var/log/php7.3-fpm/*.log
{
copytruncate
maxage 365
missingok
monthly
notifempty
rotate 12
}

Direktive hinzufügen

Sudo nano /etc/Apache2/sites-available/example.com.conf


<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/html/example.com/public_html
    DirectoryIndex index.php index.htm index.html index.xht index.xhtml
    LogLevel info warn
    ErrorLog ${Apache_LOG_DIR}/error.log
    CustomLog ${Apache_LOG_DIR}/access.log combined

    <FilesMatch "^\.ht">
    Require all denied
    </FilesMatch>

    <files readme.html>
    order allow,deny
    deny from all
    </files>

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/example.com/public_html

    <Directory /var/www/html/example.com/public_html>
        Options Indexes FollowSymLinks Includes IncludesNOEXEC SymLinksIfOwnerMatch
        AllowOverride None
    </Directory>
</VirtualHost>

Aktivieren Sie dann die Site:

Sudo a2ensite /etc/Apache2/sites-available/example.com.conf

Nächste SSL-Site bearbeiten (In diesem Fall wurde der Certbot von Let's Encrypt zuvor zu Beginn der SSL-Zertifikatskonfiguration installiert und konfiguriert.).

Sudo nano /etc/Apache2/sites-available/example.com-le-ssl.conf

<IfModule mod_ssl.c>
    #headers for security man in the middle attack find how to enable this mod in Google
    LoadModule headers_module modules/mod_headers.so
    <VirtualHost *:443>
        Header always set Strict-Transport-Security "max-age=15768000"
        SSLEngine On
        ServerName example.com
        ServerAdmin [email protected]
        DocumentRoot /var/www/html/example.com/public_html
        <Directory /var/www/html/example.com/public_html>
        Options Indexes FollowSymLinks Includes IncludesNOEXEC SymLinksIfOwnerMatch
        AllowOverride All
        Require all granted
        DirectoryIndex index.php
        RewriteEngine On
         <FilesMatch ^/(.*\.php(/.*)?)$>
           SetHandler "fcgi://example.com:9000/var/www/html/example.com/public_html"
          </FilesMatch>
        </Directory>
    # Log file locations
    #LogLevel info ssl:warn
    LogLevel debug
    ErrorLog ${Apache_LOG_DIR}/error.log
    CustomLog ${Apache_LOG_DIR}/access.log combined

    # modern configuration
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-Apache.conf
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    #SSLCipherSuite HIGH:!aNULL:!MD5
    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM$
    SSLHonorCipherOrder on
    SSLCompression off
    SSLSessionTickets off

    <FilesMatch "^\.ht">
    Require all denied
    </FilesMatch>

    <files readme.html>
       order allow,deny
       deny from all
    </files>

</VirtualHost>
    #Stapling OCSP for Let's Encrypt certs.
    SSLUseStapling          on
    SSLStaplingResponderTimeout     5
    SSLStaplingReturnResponderErrors        off
    SSLStaplingCache        shmcb:/var/run/ocsp(128000)
</IfModule>

Sudo a2enmod proxy proxy_fcgi setenvif
Sudo systemctl reload Apache2.service
Sudo chown --recursive root:adm /etc/php/
Sudo chmod --recursive 0770 /etc/php/
Sudo chown --recursive php:adm /var/log/php7.3/
Sudo chown --recursive php:adm /var/log/php7.3-fpm/
Sudo chmod --recursive 0770 /var/log/php7.3/
Sudo chmod --recursive 0770 /var/log/php7.3-fpm/
Sudo chown --recursive php:php /var/tmp/php7.3/
Sudo chmod --recursive 0770 /var/tmp/php7.3/
Sudo a2enconf php7.3-fpm
Sudo systemctl enable php7.3-fpm.service
Sudo systemctl start php7.3-fpm.service

Denken Sie daran, einer Firewall unter Debian/Ubuntu einen Port 9000 hinzuzufügen

Sudo ufw allow 9000/tcp
Sudo ufw status

Auf CentoOS/Fedora/Red Hat

Sudo firewall-cmd --zone=public --add-port=9000/tcp --permanent
Sudo firewall-cmd --reload
Sudo firewall-cmd --list-all
Sudo firewall-cmd --state 
0
Sysadmin

ich habe den Fehler auch nach dem Wechsel zu PHP-Fpm + Apache 2.4.6 für drupal Instanzen

aber ich benutze mpm event mod

einfach einfügen

DirectoryIndex index.php funktioniert bei mir

dann sehen meine Vhost-Einstellungen wie folgt aus

<VirtualHost *:8080>
  ServerAdmin [email protected]
  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>

vielen Dank

die Standard-.htaccess-Datei von drupal muss nicht überarbeitet werden

0
sealionking