httpd-docs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <>
Subject [Httpd Wiki] Update of "PHP-FPM" by JeroenGeilman
Date Wed, 09 May 2012 22:51:39 GMT
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:

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

 * 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

This means that we can now run secure, fast, and dependable PHP code ''using only the stock
apache httpd and 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

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`: 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 '''[[|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

To work the magic with the PHP fastCGI process manager, we will be using a new module, '''[[|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/`<<BR>>
 `LoadModule proxy_fcgi_module modules/`

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://$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:// 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

Inside this vhost, add the following line:
 `ProxyPassMatch ^/info$ fcgi://`
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://$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

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message