Недавно я установил Apache 2.4 на свой локальный компьютер вместе с PHP 5.4.8 с использованием 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()
(это просто тестовый файл).
Однако если я позвоню в каталог, я получу 404 с телом File not found.
и в журнале ошибок:
[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
Хорошо, поэтому я думаю: «Может быть, сначала проверьте, есть ли файл, который нужно передать прокси:
<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>
Теперь полная перезапись уже не работает ...
Теперь у меня есть такое решение:
<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-адресов внутри подкаталога, а также для таких URL-адресов, как http://localhost/index.php/test/
Итак, вернемся к исходной точке.
Любые идеи?
После нескольких часов поиска и чтения документации Apache я пришел к решению, которое позволяет использовать пул, а также позволяет директиве Rewrite в .htaccess работать, даже если URL-адрес содержит файлы .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>
Согласно документации Apache, для параметра прокси SetHandler требуется Apache HTTP Server 2.4.10.
Я надеюсь, что это решение вам тоже поможет.
Вчера я тоже столкнулся с этой проблемой - Apache 2.4 переехал из Debian / экспериментальный в Debian / нестабильный заставляя меня заниматься этим новым материалом; не на наших производственных серверах конечно;).
Прочитав миллионы сайтов, документацию Apache, отчеты об ошибках и отладочную информацию в журнале ошибок, я наконец-то заставил все работать. Нет есть нет поддержки FPM с сокетами, все же. В конфигурации Debian по умолчанию уже некоторое время используются сокеты, поэтому пользователям Debian также придется это изменить.
Вот что работает для сайта CakePHP и PHPMyAdmin (последний требует некоторой конфигурации, если вы используете пакеты Debian), поэтому я могу подтвердить, что mod_rewrite
по-прежнему работает, как и ожидалось, для перезаписи причудливого URL.
Уведомление 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 в вашей системе, они сразу же хотят использовать одни и те же порты.)
Все, что вам нужно сделать, это установить:
ProxyErrorOverride on
И не забудьте настроить страницу клиента:
ErrorDocument 404 /path/to/error_page_file
Вот что у меня есть. Вроде работает нормально. Я поместил Drupal в подкаталог, и он переписывает работу, индексы каталогов работают, а PATH_INFO работает.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} ^/((.*\.php)(/.*)?)$
RewriteCond %2 -f
RewriteRule . fcgi://127.0.0.1:9000/%1 [L,P]
RewriteOptions Inherit
Я пытался сделать что-то подобное без перезаписи («Если» и тому подобное), но ничего не получалось.
РЕДАКТИРОВАТЬ: Обратите внимание, что если вы реализуете это как поставщик общего хостинга, это может быть проблемой безопасности. Это позволит пользователям передавать сценарии PHP на произвольный прокси-сервер fcgi. Если бы у вас был отдельный пул для каждого пользователя, это позволило бы повысить привилегии атак.
Еще одно решение (требуется 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>
Итак, здесь обработчик fcgi для PHP будет установлен, только если файл существует и если его имя совпадает с расширением файла PHP.
Кстати: Для тех, у кого есть идея установить ProxyErrorOverride к На, имейте в виду, что это действительно плохая идея. Использование этой директивы не вызывает никаких проблем. Например, любое приложение PHP, отправляющее код HTTP, такой как 503, приведет к неожиданному результату. Обработчик ошибок по умолчанию будет задействован в любых случаях, а для приложений PHP, которые предоставляют API, это действительно плохое поведение.
Лучший способ решить эту проблему - включить журналы отладки для mod_proxy, mod_rewrite и php-fpm. В apache 2.4 теперь вы можете включать журналы отладки только для определенных модулей. http://httpd.apache.org/docs/current/mod/core.html#loglevel Конфигурация для каждого модуля и каталога доступна в Apache HTTP Server 2.3.6 и более поздних версиях.
Может быть, у вас двойной слеш на каталогах?
Вот что я использую, и он отлично работает:
<LocationMatch ^(.*\.php)$>
ProxyPass fcgi://127.0.0.1:9000/home/DOMAINUSER/public_html$1
</LocationMatch>
Одна вещь, с которой я столкнулся при решении этой проблемы, заключается в том, что если вы используете комбинацию:
chroot = /path/to/site
chdir = /
В конфигурации пула fpm не передавайте полный путь к ProxyPass
директива.
ProxyPass fcgi://127.0.0.1:9020/$1
Но ТОЛЬКО, если пул на этом порту находится в режиме chrooted.
Я не уверен, связана ли проблема, но я нашел здесь частичное рабочее решение:
Кажется, трюк в том, чтобы добавить? char в .htaccess RewriteRule, например, используя:
RewriteRule ^(.*)$ index.php?/$1 [L,NS]
вместо того:
RewriteRule ^(.*)$ index.php/$1 [L,NS]
Источником проблемы, похоже, является изменение mod_rewrite в Apache 2.4.25. Я использовал уровень журнала Apache trace1 для наблюдения за "циклом", который передает $ 1 в php-fpm после того, как был передан index.php / $ 1. $ 1 генерирует ошибку «AH01071: Got error 'Primary script unknown \ n'».
Надеюсь, этот маленький лакомый кусочек поможет кому-то решить свои проблемы.
Слегка измененная версия ответа @ FrancescoA, не требующая mod_rewrite
<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>
У Linode есть отличный учебник по этой теме
По сути, вы устанавливаете обработчик для всего сервера, который будет перехватывать любые скрипты php и передавать их fast-cgi.
У меня ошибка также после перехода на php-fpm + apache 2.4.6 для экземпляров drupal
но я использую мод событий mpm
просто вставьте
DirectoryIndex index.php
работает для меня
тогда мои настройки Vhost выглядят как показано ниже
<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>
Спасибо
нет необходимости изменять файл .htaccess по умолчанию в drupal
У меня такие же проблемы на моем сервере (докер centos 7.3.16). После отслеживания журнала php-fpm я обнаружил, что отсутствует системная библиотека. 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
Это работает с Wordpress 5.1.1 и новее вместе с PHP 7.3, FastCGI, прокси, а также с MariaDB / MySQL. Проверено дважды на моих серверах. Работает как шарм.
Впервые на 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
Руководство:
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)
Проблема в том, что php 7.3 из репозитория Ondrej работает только с режимом mpm_prefork. У него есть репозиторий git, так что вы можете найти его в сети и спросить, сделает ли он php 7.3 для mpm_worker и mpm_event. Остальная конфигурация для дистрибутивов семейства 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 (в этом случае certbot от Let's Encrypt был установлен и настроен ранее в начале настройки сертификата 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
Не забудьте добавить порт 9000 в брандмауэр в Debian / Ubuntu.
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