When using Apache and PHP, the common usage is to use mod_php which effectively loads php into memory for every single Apache instance. This limits a lot of features as well because of both PHP's limits, and how mod_php works.
By using an alternative approach, loading PHP through FastCGI, you get the ability to run Apache's worker MPM, which is a multi-threaded engine of Apache allowing it to use multi-CPU/multi-core systems more effectively than the older preforking method normally used. It also speeds up PHP scripts by still preloading the PHP interpretter in a different way.
We will explain further why this approach is beneficial.
This article explains how to run PHP as a process which runs independently from Apache. It is written for server administrators who want to use a flexible and at the same time easy to manage PHP environment. The usefulness of this approach allows you to use the faster multi-threaded Apache MPM while using non-threadsafe PHP scripts.
mod_fcgid is an Apache module. It allows execution of external programs who create web documents as their output. This procedure is well-known from CGI (Common Gateway Interface) which is often used in shared hosting environments, for example to run Perl scripts.
mod_fcgid was created as a binary compatible alternative to mod_fastcgi. Both extend the traditional CGI principle with the feature that they use persistent processes, managed by a server component. This means that the web server will not launch a new process for every request as it is the case with CGI. The speed gain is enormous.
Using PHP with mod_fcgid offers a full-featured PHP environment combined with all the features that mod_fcgid provides. This solution has a lot of advantages over the traditional way of running PHP on a web server, while the only disadvantage seems to be that it is a little bit more difficult to be set up.
This manual is designed for Debian Etch servers. It expects a server running Apache 2.x. Basically this should work equally for other systems – they probably just use different paths and package names…
The following packages are required:
apt-get -u install php5-cgi libapache2-mod-fcgid apache2-mpm-worker
Remove mod_php4 / mod_php5 if not already done
a2dismod php4
a2dismod php5
Enable mod_actions and mod_fcgid
a2enmod actions
a2enmod fcgid
Raise the communication timeout (= maximum execution time) for FCGI applications in /etc/apache2/mods-enabled/fcgid.conf by adding the “IPCCommTimeout” directive:
<IfModule mod_fcgid.c>
AddHandler fcgid-script .fcgi
SocketPath /var/lib/apache2/fcgid/sock
# Communication timeout: Default value is 20 seconds
IPCCommTimeout 60
# Connection timeout: Default value is 3 seconds
#IPCConnectTimeout 3
</IfModule>
Create a new file /etc/apache2/conf.d/php-fcgid.conf:
<IfModule !mod_php4.c>
<IfModule !mod_php4_filter.c>
<IfModule !mod_php5.c>
<IfModule !mod_php5_filter.c>
<IfModule !mod_php5_hooks.c>
<IfModule mod_actions.c>
<IfModule mod_alias.c>
<IfModule mod_mime.c>
<IfModule mod_fcgid.c>
# Path to php.ini - defaults to /etc/phpX/cgi
DefaultInitEnv PHPRC=/etc/php5/cgi
# Number of PHP childs that will be launched. Leave undefined to let PHP decide.
#DefaultInitEnv PHP_FCGI_CHILDREN 3
# Maximum requests before a process is stopped and a new one is launched
#DefaultInitEnv PHP_FCGI_MAX_REQUESTS 5000
# Define a new handler "php-fcgi" for ".php" files, plus the action that must follow
AddHandler php-fcgi .php
Action php-fcgi /fcgi-bin/php-fcgi-wrapper
# Define the MIME-Type for ".php" files
AddType application/x-httpd-php .php
# Define alias "/fcgi-bin/". The action above is using this value, which means that
# you could run another "php5-cgi" command by just changing this alias
Alias /fcgi-bin/ /var/www/fcgi-bin.d/php5-default/
# Turn on the fcgid-script handler for all files within the alias "/fcgi-bin/"
<Location /fcgi-bin/>
SetHandler fcgid-script
Options +ExecCGI
</Location>
</IfModule>
</IfModule>
</IfModule>
</IfModule>
</IfModule>
</IfModule>
</IfModule>
</IfModule>
</IfModule>
Next, create the directory which is chosen by the alias, and put in a symlink to the php5-cgi binary
mkdir /var/www/fcgi-bin.d/php5-default
ln -s /usr/bin/php5-cgi /var/www/fcgi-bin.d/php5-default/php-fcgi-wrapper
Finally, restart Apache:
/etc/init.d/apache2 restart
It is also possible to run different versions of PHP, even with different users.
Enable mod_suexec:
a2enmod suexec
Create a new user:
adduser $username
For every instance of PHP, create a new subdirectory in /var/www/fcgi-bin.d:
mkdir /var/www/fcgi-bin.d/php$version-$username/
Instead of creating a symlink, this time you need to add a new file “php-fcgi-wrapper” inside this directory:
#!/bin/sh
# Wrapper for PHP-fcgi
# This wrapper can be used to define settings before launching the PHP-fcgi binary.
# Define the path to php.ini. This defaults to /etc/phpX/cgi.
#export PHPRC=/var/www/fcgi-bin.d/php5-web01/phprc
#export PHPRC=/etc/php5/cgi
# Define the number of PHP childs that will be launched. Leave undefined to let PHP decide.
#export PHP_FCGI_CHILDREN=3
# Maximum requests before a process is stopped and a new one is launched
#export PHP_FCGI_MAX_REQUESTS=5000
# Launch the PHP CGI binary
# This can be any other version of PHP which is compiled with FCGI support.
exec /usr/bin/php5-cgi
Make this script executable and change the user appropriately
# chmod a+x /var/www/fcgi-bin.d/php&lt;version&gt;-&lt;username&gt;/php-fcgi-wrapper
# chown <user>:<group> /var/www/fcgi-bin.d/php<version>-<username>/php-fcgi-wrapper
Modify the Apache configuration, e.g. in /etc/apache2/sites-enabled/web01:
<VirtualHost *:80>
Servername web01.myserver.com
DocumentRoot /var/www/websites/web01/
SuexecUserGroup <user> <group>
Action php-fcgi /fcgi-bin/php-fcgi-wrapper
Alias /fcgi-bin/ /var/www/fcgi-bin.d/php<version>-<username>/
</VirtualHost>
Notice: It is important that user and group are owned by the same user and group as defined for the wrapper script above.
Restart Apache:
/etc/init.d/apache2 restart
Website of mod_fcgid: http://fastcgi.coremail.cn/
How fast is it? Compared to mod_php5 the speed seems to be almost equal, probably just a little bit slower.
Can I turn off the PHP parser for a specific directory? Of course! You can simply disable the parser for directories. This is very useful for example to use WebDAV for editing PHP files. Using mod_php5 these files would be sent as plain HTML output:
<Location /dav/>
RemoveHandler .php
</Location>