Apache mod_fastcgi and PHP with PHP-FPM
Recently I did a server migration from an older server to a newer server and in an attempt to help stability I wanted to see if there was a better way to do PHP FastCGI. In my research I came across running PHP using the FastCGI server that spins up a PHP on a TCP/IP port and allows the web server to connect to it. However this doesn't help with spawning or keeping track of instances or error recovery.
This is where PHP-FPM comes in handy. It does all of the hard work for us, it spawns the processes and has a bunch of really awesome features that help run PHP as various different users as required with different PHP ini files and memory limits. PHP-FPM's defaults, at least from a ports install, are extremely sane and I don't really suggest changing them. After setting up PHP FPM I had to set up Apache.
mod_fcgid doesn't allow for remote connections, and as such I was unable to use
it for what I needed it for. mod_fastcgi provides the
FastCGIExternalServer configuration key, which is exactly what I needed.
"The FastCgiExternalServer directive defines filename as an external FastCGI application. If filename does not begin with a slash (
/) then it is assumed to be relative to theServerRoot. The filename does not have to exist in the local filesystem. URIs that Apache resolves to this filename will be handled by this external FastCGI application."
What this documentation does not state is that the path up to the last part of
it has to exist in the local file system. So in my first couple of attempts I
pointed it at /usr/local/www/fastcgi/php5.fcgi without having an actual fastcgi
directory located in /usr/local/www/. There are a lot of examples that require
creating a new FastCGIExternalServer for each and every VirtualHost this is
unacceptable to me, the reason they require it is because they set the
FastCGIExternalServer path to the folder where they are going to be serving
files from.
In the end I found that after creating the /usr/local/www/fastcgi directory
(and reading the mod_fastcgi source code) that all it does is make Apache
believe a file exists in a certain directory, much like Alias, except Alias
allows full paths to be aliased, not so here.
The AddType and Action add custom types and what the action should be when
such a type is encountered. In this case the action is to redirect the request
to /php5.fcgi which will handle the rest of the request. This does not require
another FastCGI section per VirtualHost as each PHP request will just get
shuttled to the php handler.
Do take note that I have specifically disallowed Apache to serve anything from
the /usr/local/www/fastcgi/ folder, except for a single file php5.fcgi
which is our FastCGIExternalServer file.
<IfModule mod_fastcgi.c> Alias /php5.fcgi /usr/local/www/fastcgi/php5.fcgi FastCGIExternalServer /usr/local/www/fastcgi/php5.fcgi -flush -host 127.0.0.1:9000 AddType application/x-httpd-fastphp5 .php Action application/x-httpd-fastphp5 /php5.fcgi <Directory "/usr/local/www/fastcgi/"> Order deny,allow Deny from all <Files "php5.fcgi"> Order allow,deny Allow from all </Files> </Directory> </IfModule>
Note that even-though in my last post concerning mod_fastcgi I as moving
away from it, I am now doing the opposite, instead of moving from
mod_fastcgi to mod_fcgid I'm back to mod_fastcgi, only because
mod_fcgid doesn't offer the same functionality.
So far this has provided far more stability, along with PHP-FPM doing all of
the process management I can now use a single PHP instance that is running on a
single port for the various web servers I am testing. At the moment I have both
Lighttpd and Apache using the same PHP-FPM instance. It is faster, less
memory is wasted and PHP-FPM is much better at process management than
mod_fastcgi or mod_fcgid.