Running two php/mysql/mariadb versions on the same apache web server

April 13, 2013 by Roberto Puzzanghera 0 comments

In a web server  very old applications must coexist with new ones. Usually old applications are no more mantained and still require old versions of php and mysql, while recent apps claim to use the latest features of your apache, php and database servers. In addition you may want to switch from MySQL to mariaDB, which is going to quickly supersede its progenitor program.

That said, how to build a web server which mounts on the same apache a variety of php/mysql/mariadb configurations? Let's consider a simple case and suppose to have an apache 2.4.x already installed and two database server, let's say mysql-5.5 and mariadb-5.5, listening on two different IPs. We would like to have two separate php versions available, let's say 5.3.x and 5.4.x, living together and connecting to mysql and mariadb respectively. Of course this procedure can be modified as you like for any number of configurations you like.

I will show how to achieve this goal by configuring php in the usual mod_php manner and by means of mod_cgid, an apache module which starts php requests as a CGI program, delivering very similar performance as mod_php. I will show how to select the proper php.ini file as well.

So, in the following I'm going to call old and new servers in this way:

  old server new server
php 5.3 5.4
apache config mod_php mod_fcgid
database mysql-5.5 mariadb-5.5

MySQL/mariadb configuration

You may want to take a look to the installation/configuration/upgrade/migration guides I wrote an howto for both the old mysql and the new mariadb:

When compiling your php, it has to find the mysql/mariadb installation folder, so you need to share it so that it will be available in the apache web server. Let's suppose that you have the two database servers already installed according to this scheme (actually these should be folders shared by the servers which host the databases):

mysql-5.5 -> /usr/local/mysql
mariadb-5.6 -> /usr/local/mariadb

apache/php configuration: php-5.3 and mod_php

This is the usual method to install php in case you need a single php version.

This is how I configure my php as module:

./configure \
        --with-mysql=/usr/local/mysql \
        --with-mysqli=/usr/local/mysql/bin/mysql_config \
        < --other-config-options \ >
        --prefix=/usr/local/php-5.3 \
        --with-apxs2=/usr/local/apache/bin/apxs

The last line builds the apache's php_module. Note that php is going to be built against mysql, which is installed in /usr/local/mysql.

Now you have to tell apache to assign to mod_php all requests for .php files. And you have to do it inside each VirtualHost which is going to mount mod_php, so that apache will know if a certain VirtualHost is going to use mod_php or mod_fcgid.

That said, save a file like this in your apache conf dir:

# file mod_php-5.3

<IfModule mod_php5.c>
 <FilesMatch \.php$>
 AddHandler php5-script .php
 </FilesMatch>
</IfModule>

This file has to be included by any VirtualHost which needs mod_php:

<VirtualHost *:80>
 DocumentRoot "/path/to/document/root"
 ServerName www.yourdomain.net
 Include "/path/to/mod_php-5.3"
</VirtualHost>

apache/php configuration: php-5.4 and mod_fcgid

Installing mod_fcgid

This module is not bundled into apache, so you must install it separately. If your apache's apxs program is not in your path you have to set the APXS environment variable to the apxs location.

APXS=/usr/local/apache/bin/apxs ./configure.apxs
make
make install

Now you have to prepare your VirtualHosts for mod_fcgid. Apache wants to know what to do with .php extensions.

Configuring and installing php as cgi

This is how you may want to configure php to look for mariadb libraries. Of course you don't have to compile the apache module here, otherwise it will overwrite the old php-5.3 module:

#!/bin/sh

./configure \
        --with-mysql=/usr/local/mariadb \
        --with-mysqli=/usr/local/mariadb/bin/mysql_config \
         <--other-config-options \>
        --prefix=/usr/local/php-5.4

The configuration is looking for mariadb in the /usr/local/mariadb folder. Of course, expecially in case of many different db server are needed, this directory is mounted from the remote (virtual) mariadb server.

At this point you should edit your php.ini and set

; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting
; this to 1 will cause PHP CGI to fix it's paths to conform to the spec.  A setting
; of zero causes PHP to behave as before.  Default is 1.  You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
cgi.fix_pathinfo=1

This would be a good choice, as remainded in the commented text.

Preparing apache for mod_fgid

Create a text file like this in you apache conf dir:

# file mod_fcgid_php-5.4

<IfModule fcgid_module>
 AddHandler fcgid-script .php
 Options +ExecCGI
 FcgidWrapper /usr/local/bin/php-wrapper .php
 FcgidInitialEnv PHPRC "/path/to/php.ini" 
</IfModule>

This file tells apache to assign to fcgid each request for .php files, to consider such files as cgi scripts and to call a wrapper executable file, which in turn sets some environment variables and execute php-cgi. The last line selects the proper php.ini file (using mod_fcgid you can't adjust the php config via apache's php_value/php_flag).

This is the content of my wrapper file /usr/local/bin/php-wrapper

#!/bin/sh
# Set desired PHP_FCGI_* environment variables.
# Example:
# PHP FastCGI processes exit after 500 requests by default.
PHP_FCGI_MAX_REQUESTS=10000
export PHP_FCGI_MAX_REQUESTS

# Replace with the path to your FastCGI-enabled PHP executable
exec /usr/local/php-5.4/bin/php-cgi

remember to give +x priviledges to the wrapper file:

chmod +x  /usr/local/bin/php-wrapper

Now you may want to configure a bit your mod_fgcid directly acting on the main config file httpd.conf:

# FcgidMaxRequestsPerProcess should be <= PHP_FCGI_MAX_REQUESTS
# The example PHP wrapper script overrides the default PHP setting.
FcgidMaxRequestsPerProcess 10000

# Uncomment the following line if cgi.fix_pathinfo is set to 1 in
# php.ini:
FcgidFixPathinfo 1

Finally you have to include the fcgid_php-5.4 file in each VirtualHost which needs to load php as cgi

<VirtualHost *:80>
 DocumentRoot "/path/to/document/root"
 ServerName www.example.net
 Include "/path/to/mod_fcgid_php-5.4"
</VirtualHost>

Add a comment