web-dev-qa-db-ja.com

Apache 2.4 + PHP-FPM + ProxyPassMatch

最近、Apache 2.4をローカルマシンにPHP 5.4.8 with PHP-FPMを使用して)インストールしました。

すべてがかなりスムーズに進みました(しばらくすると...)が、奇妙なエラーがまだあります。

次のように、ApacheをPHP-FPM用に構成しました。

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

これは機能します。たとえば、_http://localhost/info.php_を呼び出すと、正しいphpinfo()を取得します(これは単なるテストファイルです)。

ただし、ディレクトリを呼び出すと、本文_File not found._の404が返され、エラーログに表示されます。

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

更新

私は今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>
_

しかし問題は次のとおりです:_http://localhost/_では自動的に_http://localhost/index.php_が要求されるため、常にリダイレクトされます。

_DirectoryIndex index.php index.html
_

アップデート2

わかりましたので、「まずプロキシに渡すファイルがあるかどうかを確認します。

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

これで完全な書き換えは機能しなくなりました...

アップデート3

今私はこの解決策を持っています:

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

最初に、PHP-FPMに渡すファイルがあることを確認し(fullおよびabsoluteパスを使用)、次に書き換えを行います。

これは、サブディレクトリ内でURLの書き換えを使用している場合は機能しません。また、_http://localhost/index.php/test/_などのURLの場合は失敗します。そのため、正方形に戻ります。


何か案は?

32
apfelbox

Apacheドキュメントを何時間も検索して読んだ後、プールを使用できるようにするソリューションを思いつきました。また、URLに.phpファイルが含まれている場合でも、.htaccessのRewriteディレクティブが機能するようにしています。

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

Apacheのドキュメントに従って、SetHandlerプロキシパラメータにはApache HTTP Server 2.4.10が必要です。

この解決策があなたにも役立つことを願っています。

36
FrancescoA

あなたがする必要があるすべては設定することです:

 ProxyErrorOverride on

また、次の方法で顧客ページを設定することを忘れないでください。

ErrorDocument 404 /path/to/error_page_file    
4
Shiqi Zhong

さらに別のソリューション(Apache> = 2.4.10が必要)-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>

したがって、ここではPHPのfcgiハンドラーは、ファイルが存在し、その名前がPHPファイル拡張子と一致する場合にのみ設定されます。

BTW:ProxyErrorOverrideOnに設定するアイデアがある場合、これは本当に悪いアイデアであることに注意してください。このディレクティブを使用しても問題は発生します。たとえば、PHPアプリケーションがHTTPコード(503など)を送信すると、予期しない結果が発生します。デフォルトのエラーハンドラはすべてのケースに関係し、PHP APIを提供します。これは本当に悪い動作です。

2
Nuxwin

これは私が持っているものです。大丈夫そうです。私はサブディレクトリにDrupalを置き、その書き換え作業、ディレクトリインデックス作業、PATH_INFO作業を行います。

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

私は書き換えなしでこのようなことをしようとしましたが( "If"など)、何も動作しませんでした。

編集:これを共有ホスティングプロバイダーとして実装する場合、セキュリティ上の問題になる可能性があることに注意してください。これにより、ユーザーはPHPスクリプトを任意のfcgiプロキシに渡すことができます。ユーザーごとに個別のプールがある場合、特権の昇格攻撃が可能になります。

2
RockinRoel

これを解決する最良の方法は、mod_proxy、mod_rewrite、およびphp-fpmのデバッグログをオンにすることです。 Apache 2.4では、特定のモジュールのみのデバッグログをオンにできるようになりました。 http://httpd.Apache.org/docs/current/mod/core.html#loglevel モジュールごとおよびディレクトリごとの構成は、Apache HTTPサーバー2.3.6以降で使用できます

多分あなたはディレクトリでダブルスラッシュを取得していますか?

これが私が使っているもので、うまくいきます:

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

この問題の処理で遭遇したことの1つは、次の組み合わせを使用する場合です。

chroot = /path/to/site
chdir = /

Fpmプール構成では、ProxyPassディレクティブに絶対パスを渡さないでください。

ProxyPass fcgi://127.0.0.1:9020/$1

ただし、そのポートのプールがchrootされている場合は-のみ-です。

1
thinice

問題が関連しているかどうかはわかりませんが、ここでは部分的に機能する解決策を見つけました:

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

トリックは?を追加しているようです。 .htaccess RewriteRuleのchar、たとえば次を使用:

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

の代わりに:

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

問題の原因は、Apache 2.4.25のmod_rewriteの変更にあるようです。 Apache trace1ログレベルを使用して、index.php/$ 1が渡された後に$ 1をphp-fpmに渡す「ループ」を観察しました。 $ 1は「AH01071:Got error 'Primary script unknown\n'」エラーを生成します。

この小さな一口が誰かが彼らの問題を解決するのを助けることを願っています。

1
Biapy

Mod_rewriteを必要としない@FrancescoAの回答のわずかに変更されたバージョン

<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にはこのテーマに関する素晴らしいチュートリアルがあります

基本的に、phpスクリプトをキャッチしてfast-cgiに渡すサーバー全体のハンドラーをセットアップします。

0
styks

私のサーバー(centos 7.3.16 docker)でも同じ問題に直面しています。 php-fpmログを追跡した後、sys libが見つからないことがわかりました。 WARNING: [pool www] child 15081 said into stderr: "php-fpm: pool www: symbol lookup error: /lib64/libnsssysinit.so: undefined symbol: PR_GetEnvSecure"それから、nsprを再インストールし、機能します。何らかの方法を試しても解決策が見つからない場合は、これを試してみてください。 yum -y install/reinstall nspr

0
lemon

これはWordpress 5.1.1以降およびPHP 7.3、FastCGI、プロキシ、MariaDB/MySQLとも一緒に動作します。サーバー上で2回チェックされます。チャーム。

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

このファイルを編集します。

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

これを貼り付けます:

[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

Srw-rw-rw-を与える必要があります。

または、Debian/Ubuntuでの設定方法

チュートリアル:

ソース: 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)

問題は、Ondrejリポジトリのphp 7.3がmpm_preforkモードでのみ機能することです。彼はgitリポジトリを持っているので、ネットで見つけて彼に尋ねることができます。mpm_workerとmpm_eventのphp 7.3を作成しますか。 Debianファミリーディストリビューションの残りの構成は以下のとおりです。


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

ペースト


[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

ペースト


[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

ペースト


[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

これをtxtファイルにコピーします:

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

それを削除してから、上記の代わりに貼り付けます。

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

ディレクティブを追加

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>

次に、サイトを有効にします。

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

次に、SSLサイトを編集します(この場合、Let's Encryptのcertbotは、SSL証明書構成の最初にインストールおよび構成されています)。

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

Debian/Ubuntuのファイアウォールにポート9000を追加することを忘れないでください

Sudo ufw allow 9000/tcp
Sudo ufw status

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

drupalインスタンスに対してphp-fpm + Apache 2.4.6に切り替えた後もエラーが発生します

しかし、私はmpm event modを使用しています

挿入するだけ

DirectoryIndex index.phpは私のために働く

私の仮想ホスト設定は以下のようになります

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

ありがとう

drupalのデフォルトの.htaccessファイルを修正する必要はありません

0
sealionking