Apache 2.4 + PHP-FPM + ProxyPassMatch


31

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

すべてが順調に進みました(しばらくしてから...)が、まだ奇妙なエラーがあります:

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

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

しかし、問題は:onが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に渡すファイルがあることをまず確認、フル絶対パス)、その後、書き換えを行うには。

これは、サブディレクトリ内でURL書き換えを使用する場合は機能しません。また、http://localhost/index.php/test/ So back to square oneのようなURLでも失敗します。


何か案は?

回答:


34

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サーバー2.4.10が必要です。

このソリューションがあなたにも役立つことを願っています。


2
これは、ここでの他のすべてが現代のセットアップ(レッツ・発言のDebianの安定)のためのがらくたである、間違いなく2015年のための答えである
ドミトリDB

1
私はかなり長い間、この同じ問題で頭を壁にぶつけていましたが、あなたと非常によく似た設定をしています。.htaccess Rewriteディレクティブを投稿していただけますか?私が理解していることから、この回答のすべては、httpd.d / site.confファイルにあるものだけです。
デビッドW

1
現時点では、このRewriteRuleを使用すると、config.php ファイルがエイリアスディレクトリ内にあり、%{DOCUMENT_ROOT} /%{REQUEST_URI}に存在しない場合、プレーンにファイルを公開する可能性があるため、非常に危険です。
ズラキス

1
驚くべき9行のコード。これは聖杯であり、私にとって100%働く唯一のことです。ただの補足:LocationMatchを使用してソリューションから切り替える場合、fcgi urlに絶対ファイルパスを追加する必要はありません。プロキシを有効にして、Apacheのログを書き換えて、これに注意してください。
フィル

1
+1は、この投稿が他のすべてのリソースとは異なり、「一意のドメイン名文字列」が何を表しているのかを理解するのに役立ちました。
16

10

昨日もこの問題に遭遇しました。Apache2.4はDebian / experimentalからDebian / unstableに移行し、この新しいものに対処せざるを得なくなりました。もちろん、本番サーバーではありません;)。

何百万ものサイト、Apacheのドキュメント、バグレポート、エラーログのデバッグ出力を読んだ後、ようやく動作するようになりました。いいえ、ソケットを使用したFPMのサポートはまだありません。デフォルトのDebian構成では、しばらくの間ソケットを使用しているため、Debianユーザーもソケットを変更する必要があります。

CakePHPサイトとPHPMyAdmin(Debianパッケージを使用している場合は後者がいくつかの設定を必要とします)でmod_rewrite機能するものを以下に示します。

注意してくださいDirectoryIndex index.php、これはあなたの設定がどれも「フォルダ」で動作しなかった理由かもしれません(少なくともここでは動作しませんでした)。

まだFile not found.ディレクトリを取得していますが、解析できるインデックスファイルがない場合のみです。それも取り除きたいのですが、今のところそれほど重要ではありません。


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

上記のvhostは、ルートの.htaccessで次のように完全に機能します。

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

私はあなたが何を意味するのかよくわかりませんURL rewriting inside a subdirectory(ルートのindex.phpに書き換えているだけです)。


(ああ、あなたはXdebugがあなたのシステムのFPMと競合しないことを確認する必要があります、彼らは同じポートを使いたいと思います。)


これは良い解決策ですが、残念ながら、WordPressマルチサイトなどで.phpを含むURLを書き換える必要がある場合、このアプローチは機能しません。/ms_blog_1/wp-admin/load-scripts.php?blah=blah
Phil

私にとっては、DirectoryIndex index.html問題の仮想ホストにオーバーライドを追加するだけで修正されました。私が持っている場合DirectoryIndex index.php、他のPHPファイルが「ファイルが見つかりません」および「プライマリスクリプトが不明」というエラーを出すことになります。私の場合、index.htmlphpファイルがありますtest.php
-geerlingguy

4

設定するだけです:

 ProxyErrorOverride on

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

ErrorDocument 404 /path/to/error_page_file    

2

これは私が持っているものです。それはうまくいくようです。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

さらに別のソリューション(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ファイル拡張子と一致する場合にのみ、PHPのfcgiハンドラーが設定されます。

ところで:ProxyErrorOverrideOnに設定する考えを持つ人にとって、これは本当に悪い考えであることに注意してください。このディレクティブを使用しても問題が発生するわけではありません。たとえば、503などのHTTPコードを送信するPHPアプリケーションは、予期しない結果につながります。デフォルトのエラーハンドラーは、APIを提供するPHPアプリケーションの場合と、どのような場合にも関係しますが、これは実際に悪い動作です。


残念ながら、このソリューションを使用すると、「AH01071:Got error 'Primary script unknown \ n'」エラーがまだ発生していました。
klor

1

これを解決する最善の方法は、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

この問題に対処する際に出くわしたことの1つは、次の組み合わせを使用する場合です。

chroot = /path/to/site
chdir = /

fpmプール構成では、ProxyPassディレクティブへのフルパスを渡さないでください。

ProxyPass fcgi://127.0.0.1:9020/$1

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


1

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

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'」エラーを生成します。

この小さな情報が誰かの問題解決に役立つことを願っています。



0

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

しかし、私はmpmイベント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ファイルを修正する必要はありません


[2018年4月25日01:41:31.526781 2018] [proxy_fcgi:error] [pid 2012:tid 140181155772160](70007)指定されたタイムアウトが期限切れになりました:[client 127.0.0.1:60308] AH01075:Error dispatching request to:、referer:www / admin / reports
sealionking

0

サーバー(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

これは、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 admin@example.com
    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 admin@example.com
        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 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.