Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Httpd Wiki" for change 
notification.

The "PHP-FPM" page has been changed by JeroenGeilman:
http://wiki.apache.org/httpd/PHP-FPM

New page:
= High-performance PHP on apache httpd 2.4.x using mod_proxy_fcgi and php-fpm. =

With the release of apache httpd 2.4 upon an unsuspecting populace, we have 
gained some very neat functionality regarding apache and php: the ability to 
run PHP as a fastCGI process server, and address that fastCGI server ''directly 
from within apache'', via a dedicated proxy module (mod_proxy_fcgi.)

 * starting from release 5.3.3 in early 2010, PHP has merged the php-fpm 
fastCGI process manager into its codebase, and it is now (as of 5.4.1) quite 
stable.
 . php-fpm was previously found at http://php-fpm.org/

This means that we can now run secure, fast, and dependable PHP code ''using 
only the stock apache httpd and php.net releases''; no more messing around with 
'''suphp''' or '''suexec''' - or, indeed, '''mod_php'''.
----

=== php-fpm ===
  '''prerequisites''': installing software packages, editing configuration 
files, controlling service daemons.

>From release 5.3.3 onwards, PHP now includes the fastCGI process manager 
>(php-fpm) in the stock source code.<<BR>>
Your distribution or OS will either include it in the stock PHP package, or 
make it available as an add-on package; you can build it from source by adding 
`--enable-fpm` to your ./configure options.

This provides us with a new binary, called `php-fpm`, and a default 
configuration file called `php-fpm.conf` is installed in `/etc`.

The defaults in this file should be okay to get you started, but be aware that 
your distribution may have altered it, or changed its location.<<BR>>

Inside this configuration file you can create an arbitrary number of fastcgi 
"pools" which are defined by the IP and port they listen on, just like apache 
virtualhosts.

The most important setting in each pool is the ''socket'' (IP and port) php-fpm 
will be listening on to receive fastCGI requests; this is configured using the 
`listen` option.<<BR>>
The default pool, `[www]`, has this configured as `listen 127.0.0.1:9000`: it 
will only respond to requests on the local loopback network interface 
(localhost), on TCP port 9000.<<BR>>
Also of interest are the ''per-pool'' `user` and `group` options, which allow 
you to run that specific fpm pool under the given uid and gid; __goodbye 
suphp__!

Let's just use the defaults as shipped and start the php-fpm daemon; if your 
distro uses the provided init script, run
 `/etc/init.d/php-fpm start`
Or if not, start it manually with
 `php-fpm -y /path/to/php-fpm.conf -c /path/to/custom/php.ini`
If you don't provide php-fpm with its own `php.ini` file, the ''global'' 
php.ini will be used.<<BR>>
__Remember__ this when you want to include more or less extensions than the CLI 
or CGI binaries use, or need to alter some other values there.

You can include per-pool `php.ini` values in the same way you would define 
these in apache previously for mod_php, using `php_[admin_](flag|value)`.

See the 
'''[[http://www.php.net/manual/en/install.fpm.configuration.php|official PHP 
documentation for fpm]]''' for all possible configuration options.

I also changed the php-fpm.conf `logging` option so I can easily see what is 
being logged specifically by php-fpm:
 `error_log /var/log/php-fpm.log`
If you don't set a php-fpm logfile, errors will be logged as defined in 
`php.ini`.

 Side note: you can force a running php-fpm to reload its configuration  by 
sending it a SIGUSR2 signal.; SIGUSR1 will cycle the log files (perfect for a 
logrotate script!). A little experimentation goes a long way ;)

That's php-fpm taken care of; if there were no errors during startup it should 
be listening and ready for connections.
----
=== apache httpd 2.4 ===

 '''prerequisites''': editing httpd.conf; understanding vhost context; 
understanding URL-to-filesystem namespace mapping; controlling the apache httpd 
daemon

The release of apache httpd 2.4 has introduced two noteworthy features: a new 
proxy module specifically for fastCGI (mod_proxy_fcgi), and the move to the 
'''event''' MPM as the default apache process manager.

As with the worker MPM of the previous version, the threaded model of this MPM 
causes issues when mod_php is used with ''non-thread-safe'' 3rd-party PHP 
extensions.<<BR>>
This has been a bane of mod_php users ever since apache 2.2 was released, 
practically forcing them to cobble together fastcgi solutions, or use the much 
slower and memory-hungry prefork MPM.

To work the magic with the PHP fastCGI process manager, we will be using a new 
module, 
'''[[http://httpd.apache.org/docs/2.4/mod/mod_proxy_fcgi.html|mod_proxy_fcgi]]''',
 which is intended specifically for communicating with (possibly external) 
fastCGI servers.

Make sure you include the proxy_fcgi module in your httpd.conf so we can use 
its features; since this requires the base proxy module, ensure both are loaded 
(uncommented):

 `LoadModule proxy_module modules/mod_proxy.so`<<BR>>
 `LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so`

Now, there are different ways to actually forward requests for .php files 
''to'' this module, ranging from everything (using ProxyPass) to very specific 
or rewritten files or patterns (using mod_rewrite with the [P] flag).<<BR>>
The method I chose (using ProxyPassMatch) lies somewhere in between these in 
complexity and flexibility, since it allows you to set one rule for all PHP 
content of a specific vhost, but will only forward .php files (or URLs that 
contain the text `.php` somewhere in the request)

Edit the configuration for a vhost of your choice, and add the following line 
to it:
 `ProxyPassMatch ^/(.*\.php(/.*)?)$ 
fcgi://127.0.0.1:9000/path/to/your/documentroot/$1`

Look confusing ? Let's run through it:
 ProxyPassMatch:: only proxy content that matches the specified regex pattern; 
in this case:
 ^/(.*\.php(/.*)?)$:: from the documentroot onwards, match everything ending in 
.php (with the dot escaped), optionally followed by a slash and any continued 
path you like (some applications use this so-called '''Path``Info''' to pass 
arguments to the php script.)<<BR>>
 The `^` (caret) and `$` (dollar) signs are used to ''anchor'' both the 
absolute __start__ and __end__ of the URL, to make sure no characters from the 
request escape our pattern match.<<BR>>
 The nested parentheses enable us to refer to the entire request-URI (minus the 
leading slash) as `$1`, while still keeping the trailing pathinfo optional.

 fcgi://127.0.0.1:9000:: forward via mod_proxy_fcgi, using the fastCGI 
protocol, to the port our php-fpm daemon is listening on.<<BR>>
 This determines which fastcgi ''pool'' will serve requests proxied by this 
rule.
 /path/to/your/documentroot/:: IMPORTANT! This must ''exactly'' match the 
'''real''' filesystem location of your php files, because that is where the 
php-fpm daemon will look for them.<<BR>>
  php-fpm just interprets the php files passed to it; it is not a web server, 
nor does it understand your web servers' namespace, virtualhost layout, or 
aliases.<<BR>>
 IMPORTANT! __Read the above again__
 $1:: expands to the entire request-URI from the original request, minus the 
leading slash (because we already added that above.)
----
An example, you say ? Very well, have an
==== example ====
Say you want to be able to conjure up the standard php info page listing all 
compiled-in and loaded extensions, and all runtime configuration options and 
script info.

We first create a file, info.php, by running the following:
 `echo "<?php phpinfo() ?>" > /var/www/info.php`
NOTE you may need to do this as `root`, depending on the permissions set on 
/var/www.
 I assume /var/www is the documentroot of an existing vhost; this is the case 
on most major distributions.

Inside this vhost, add the following line:
 `ProxyPassMatch ^/info$ fcgi://127.0.0.1:9000/var/www/info.php`
Reload apache with `apachectl graceful` and you can now call up the phpinfo 
page using http://your-vhost/info
  
This is a very simple example, mapping one unique URL to a single PHP file.

Aha, I hear you say - so what about something that's actually useful ?

In case you want to proxy '''all''' `.php` files in your vhost to the fcgi 
server using their real php file locations, you can use a more flexible match:
 `ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/$1`
Again, assuming `/var/www` is the documentroot of the vhost in question.

__Don't forget to reload apache after making any changes to a vhost or other 
configuration file.__

---------------------------------------------------------------------
To unsubscribe, e-mail: docs-unsubscr...@httpd.apache.org
For additional commands, e-mail: docs-h...@httpd.apache.org

Reply via email to