Configure Apache to work with PHP4 and PHP5

Andreas Korthaus  Author

Updated January 21, 2006

1.  Introduction

There are many ways to make Apache work with two PHP versions in parallel. The easiest way is to use PHP4 and PHP5 as a CGI binary, or PHP4 as CGI binary and PHP5 as Apache module (or the other way around). In this Howto Apache-2.x paths are used, but it will work with Apache-1.x paths as well (generally, just omit the 2).

For instructions how to upgrade your old dev-php/php to the new dev-lang/php packages, have a look at the Upgrade Guide.

Important: Don't use PHP4 and PHP5 cgi or PHP4 CGI and PHP5 module in a multi-user / shared-hosting environment! You should use CGI with suPHP there, which makes it possible to use PHP4 and PHP5 together too (see PHP4 CGI and PHP5 CGI using suPHP for details)!

Warning: It's not possible to run PHP4 and PHP5 module together in one Apache server, because both export the same symbols!

2.  Alternative 1: PHP4 CGI and PHP5 CGI

Install PHP4 and PHP5

Add cgi and force-cgi-redirect USE flag to /etc/portage/package.use:

Code Listing 2.1: /etc/portage/package.use

=dev-lang/php-4* cgi force-cgi-redirect
=dev-lang/php-5* cgi force-cgi-redirect

Note: Putting force-cgi-redirect into your USE flags is recommended for security.

Emerge PHP4 and PHP5:

Code Listing 2.2: emerge PHP

emerge '=dev-lang/php-4*' '=dev-lang/php-5*'

Global/Default Configuration for PHP4 CGI

Requests to files ending with .php, .php3, .php4 or .phtml should be handled by PHP4 CGI (this can be easily changed). Create a /etc/apache2/modules.d/php4-cgi.conf, which will be included by httpd.conf automatically:

Code Listing 2.3: /etc/apache2/modules.d/php4-cgi.conf

# handler for PHP 4 scripts
<IfDefine PHP4CGI>
    ScriptAlias /php4-cgi /usr/lib/php4/bin/php-cgi	
    Action php4-cgi /php4-cgi
    AddHandler php4-cgi .php4 .php3 .php .phtml
</IfDefine>

Global/Default Configuration for PHP5 CGI

Requests to files ending with .php5 should be handled by PHP5 CGI (this can be easily changed). Create a /etc/apache2/modules.d/php5-cgi.conf, which will be included by httpd.conf automatically:

Code Listing 2.4: /etc/apache2/modules.d/php5-cgi.conf

# handler for PHP 5 scripts
<IfDefine PHP5CGI>
    ScriptAlias /php5-cgi /usr/lib/php5/bin/php-cgi	
    Action php5-cgi /php5-cgi
    AddHandler php5-cgi .php5
</IfDefine>

Per Directory/VHost Configuration of PHP version

You can use a <VirtualHost>, <Location>, <Directory> directive or even a .htaccess file to configure handling of scripts ending with .php to use either PHP4 CGI or PHP5 CGI, depending on where the script is located. Use the AddHandler directive to select the PHP versions to handle the requests:

Code Listing 2.5: example for <Location> in Apache configuration

<VirtualHost *:80>

    DocumentRoot  /var/www/example.com/htdocs
    ServerName www.example.com

    <Location /php4>
    	AddHandler php4-cgi .php
    </Location>

    <Location /php5>
    	AddHandler php5-cgi .php
    </Location>

</VirtualHost>

Code Listing 2.6: alternative Apache configuration using <Directory>

<VirtualHost *:80>

    DocumentRoot /var/www/example.com/htdocs
    ServerName www.example.com

    <Directory /var/www/example.com/htdocs/php4>
    	AddHandler php4-cgi .php
    </Directory>

    <Directory /var/www/example.com/htdocs/php5>
    	AddHandler php5-cgi .php
    </Directory>

</VirtualHost>

This way you can configure Apache which PHP handler to use for every location or directory!

Note: Make sure that you have configured a default handling for PHP4 CGI and PHP5 CGI as described in the previous section.

set APACHE2_OPTS

By using the APACHE2_OPTS variable in /etc/conf.d/apache2 you can easily configure Apache to handle PHP4 and PHP5 as CGIs now:

Code Listing 2.7: /etc/conf.d/apache2

APACHE2_OPTS="-D PHP4CGI -D PHP5CGI"

3.  Alternative 2: PHP4 CGI and PHP5 Apache module

Note: PHP4 Apache module and PHP5 CGI works as well, you only need to change the configuration accordingly.

Install PHP4 and PHP5

Add cgi and force-cgi-redirect USE flag for PHP4 and apache2 for PHP5 to /etc/portage/package.use:

Code Listing 3.1: etc/portage/package.use

=dev-lang/php-4* cgi force-cgi-redirect
=dev-lang/php-5* apache2

Note: Putting force-cgi-redirect into your USE flags is recommended for security.

Emerge PHP4 and PHP5:

Code Listing 3.2: emerge PHP

emerge '=dev-lang/php-4*' '=dev-lang/php-5*'

Global/Default Configuration for PHP4 CGI

Requests to files ending with .php3, .php4 or .phtml should be handled by PHP4 CGI (this can be easily changed). Create a /etc/apache2/modules.d/php4-cgi.conf, which will be included by httpd.conf automatically:

Code Listing 3.3: /etc/apache2/modules.d/php4-cgi.conf

# handler for PHP 4 scripts
<IfDefine PHP4CGI>
    ScriptAlias /php4-cgi /usr/lib/php4/bin/php-cgi	
    Action php4-cgi /php4-cgi
    AddHandler php4-cgi .php4 .php3 .php .phtml
</IfDefine>

Global/Default Configuration for PHP5 module

If the PHP ebuild installs an Apache module, it will also automatically install a configuration file to /etc/apache2/modules.d/70_mod_php5.conf.

Requests to files ending with .php5, as well as files ending with .phps (PHP source files), will be handled by the PHP5 Apache module (this can be easily changed).

To achieve this, you need to edit the default configuration file and make it look like this:

Code Listing 3.4: /etc/apache2/modules.d/70_mod_php5.conf

<IfDefine PHP5>

    # Load the module first 
    <IfModule !sapi_apache2.c>
        LoadModule php5_module    modules/libphp5.so 
    </IfModule>

    # Set it to handle the files 
    <IfModule mod_mime.c>
        AddType application/x-httpd-php .php5 
        AddType application/x-httpd-php-source .phps 
    </IfModule>

    AddDirectoryIndex index.php index.phtml 
</IfDefine>

Per Directory/VHost Configuration of PHP version

You can use a <VirtualHost>, <Location>, <Directory> directive or even a .htaccess file to configure handling of scripts ending with .php to use either PHP4 CGI or PHP5 module, depending on where the script is located. Use the AddHandler directive to select the PHP versions to handle the requests:

Code Listing 3.5: example for <Location> in Apache configuration

<VirtualHost *:80>

    DocumentRoot  /var/www/example.com/htdocs
    ServerName www.example.com

    <Location /php4>
    	AddHandler php4-cgi .php
    </Location>

    <Location /php5>
    	AddHandler application/x-httpd-php .php
    </Location>

</VirtualHost>

Code Listing 3.6: alternative Apache configuration using <Directory>

<VirtualHost *:80>

    DocumentRoot /var/www/example.com/htdocs
    ServerName www.example.com

    <Directory /var/www/example.com/htdocs/php4>
    	AddHandler php4-cgi .php
    </Directory>

    <Directory /var/www/example.com/htdocs/php5>
    	AddHandler application/x-httpd-php .php
    </Directory>

</VirtualHost>

This way you can configure Apache which PHP handler to use for every location or directory!

Note: Make sure that you have configured a default handling for PHP4 CGI as described in the previous section.

set APACHE2_OPTS

By using the APACHE2_OPTS variable in /etc/conf.d/apache2 you can easily configure Apache to handle PHP4 as CGI and PHP5 as module now (or the other way around):

Code Listing 3.7: /etc/conf.d/apache2

APACHE2_OPTS="-D PHP4CGI -D PHP5"

4.  Alternative 3: PHP4 and PHP5 CGI with suPHP

Install PHP4 and PHP5

Add cgi and force-cgi-redirect USE flag to /etc/portage/package.use:

Code Listing 4.1: /etc/portage/package.use

=dev-lang/php-4* cgi force-cgi-redirect
=dev-lang/php-5* cgi force-cgi-redirect

Emerge PHP4 and PHP5:

Code Listing 4.2: emerge PHP

emerge '=dev-lang/php-4*' '=dev-lang/php-5*'

Note: Putting force-cgi-redirect into your USE flags is recommended for security.

Install mod_suphp

Code Listing 4.3: emerge mod_suphp

emerge mod_suphp

A few notes on it's USE flags:

USE flag description
checkpath checks if script resides in DOCUMENT_ROOT
mode-force runs scripts with UID/GID specified in Apache configuration (i.e., apache:apache)
mode-owner runs scripts with owner UID/GID
mode-paranoid runs scripts with owner UID/GID but also checks if they match the UID/GID specified in the Apache configuration

Note: If you don't choose any of the mode flags, the ebuild defaults to paranoid (which won't probably suit your needs).

Global/Default Configuration for PHP

By using the APACHE2_OPTS variable in /etc/conf.d/apache2 you can easily configure Apache to handle PHP4 and PHP5 through suPHP now:

Code Listing 4.4: /etc/conf.d/apache2

APACHE2_OPTS="-D SUPHP"

Change PHP handler to handle requests to .php scripts

By default, requests to files ending with .php, .php5, or .phtml will be handled by PHP5 CGI and files ending with .php4 by PHP4 CGI. This can be easily changed in /etc/suphp.conf:

Code Listing 4.5: /etc/suphp.conf

[handlers]
;Handler for php-scripts
x-httpd-php=php:/usr/lib/php4/bin/php-cgi
x-httpd-php5=php:/usr/lib/php5/bin/php-cgi
x-httpd-php4=php:/usr/lib/php4/bin/php-cgi
x-httpd-phtml=php:/usr/lib/php4/bin/php-cgi

The above example reverses the default mod_suphp handlers to use PHP4 by default, only files ending with .php5 will now be handled by PHP5 CGI.

5.  More Alternatives

In this guide we have focussed on the easiest alternatives to get PHP4 and PHP5 running in parallel. As mentioned before there are more alternatives. We will list some of them in this chapter, and point you to other sites where you can get more detailed information.

Running PHP4 and PHP5 module using 2 Apache instances

If you have one Apache installed, you can run two instances of it. You only need to create a second configuration file (httpd.conf) with different settings (e.g. load PHP5 module, not PHP4 module...). But you cannot bind 2 Apache instances to the same port-IP combination, so you have to use a different IP or port in the 2nd configuration file. At Apache startup you can use the -f switch to set the config file to use, which can be easily implemented by copying and changing the original RC script shipped with the Apache ebuild.

The basic steps to make it work on Gentoo:

Further information:

Hiding the 2nd Apache instance using mod_proxy

Basically it works the same as explained above, but solved the problem with using different IPs / ports: By using mod_proxy, you can use the reverse proxy functions to hide the 2nd Apache instance from users, by passing requests transparently to the 2nd Apache instance.

The basic steps to make it work on Gentoo:

Further information:

Using FastCGI

FastCGI is another alternative, which is as fast as or faster than a PHP module and does not suffer from threading issues (like PHP module if used with a threaded Apache MPM like "worker"), because it's not embedded in the webserver process.

The basic steps to make it work on Gentoo:

Further information:

6.  Restart Apache

After the installation and configuration please don't forget to restart your Apache to load the new configuration:

Code Listing 6.1: restart Apache

/etc/init.d/apache2 restart