Multiple PHP Instances With One Apache


 

Long-winded Introduction

It took me a couple of days to figure this out due to lack of decent tutorials and not enough confidence in my Linux skills to build programs from source. I think I have the hang of it now, and write this up with the intent on providing another, or the only, tutorial on setting up CentOS 5 with multiple instances of PHP using one Apache install. That being said, there are a number of good tutorials out there, just none of them explicitly for CentOS and some leave out some details that n00bs like me get confused about.

PHP4 and PHP5 on SuSE 10.1 – This was by far the most helpful of the tutorials. Even though it was written for SuSE, it works almost straight across for CentOS.

There is also a great list of instructions in the comments on the php.net site under installing PHP for Apache 2.0 on Unix systems (see http://www.php.net/manual/en/install.unix.apache2.php#90478).

I found this one after I wrote up this tutorial at http://cuadradevelopment.com. It’s a bit different, but should work as well.

There are basically two different ways I could have done this. 1- run a single instance of Apache, and run one instance of PHP as a module, and other installs as CGI. 2- run several instances of Apache, each with it’s own instance of PHP as a module. I chose to do the first method for no particular reason. Dreamhost has a post about the good and bad with running PHP as CGI.

So basically, the steps are: 1. Set up Apache and have PHP install as a module. 2. Configure and make another instance of PHP to run as CGI. 3. Add a virtual host to Apache running under a different port to access the PHP as CGI.

Set up Apache with PHP module

So here’s what I did to get the basic Apache, PHP and MySQL working. This sets up the first PHP install to run as a module in Apache:

From a clean install of CentOS 5 (virtually no packages selected during initial install), I installed the following packages:

$ yum install gcc make subversion ImageMagick php php-cli php-common php-ldap php-mysql php-pdo php-pear php-devel bzip2-devel libxml2-devel mysql mysql-server mysql-devel mod_auth_mysql httpd httpd-manual

From there I needed to get PHP 5.2.x, so I did the following to get PHP, Apache, MySQL and PEAR all set up.

  1. Step 1: GET PHP 5.2.x
    Check out instructions and packages here: http://blog.famillecollet.com/pages/Config-en

    Copy the /etc/php.ini file from the /etc/php.ini.default:

    Change the following lines:

    • 1. upload_max_filesize = 20M #line 573
    • 2. mysql.default_socket =/path/to/mysql/mysql.sock #about line 736
    • 3. mysqli.default_socket =/path/to/mysql/mysql.sock #about line 771
  2. Step 2:Edit /etc/httpd/conf/httpd.conf by changing the following lines
    • 1. Listen xxx.xxx.xxx.xxx:80 #line 134
    • 2. ServerAdmin admin@email.org #line 251
    • 3. ServerName somesite.org #line 265
    • 4. DocumentRoot ”/path/to/htdocs” #line 282
    • 5. <Directory ”/path/to/htdocs”> #line 307
    • 6. AllowOverride All #line 328
    • 7. DirectoryIndex index.php index.html index.html.var #line 392
  3. Step 3: Create the /etc/my.cnf file for MySQL
    [code]

    [/code]
  4. Step 4: Start apache and mysql and set them to start on boot up:

  5. Step 5: Set the MySQL password for root

  6. Step 6: install Phing and other PEAR packages

Configure second version of PHP

From here we need to install a second version of PHP. Grab the version you want from http://www.php.net/releases/, and stick that any where you want to (usually your root’s home directory is fine). I’m installing PHP 5.2.4, so I’ll use that in my examples.

Unpack the tarball and enter the directory it created.

Now, you’ll need to determine which modules you need to install. For this part I used the steps from the php.net comment under “my approach for determining required modules” (copied here, without permission, but with lots of gratitude and full credit going to the author of the comment).

After doing all of that, I had the following in phpconfigure.sh
[code lang=”bash”]
#!/bin/bash
./configure –prefix=/usr/share/ –datadir=/usr/share/php –libdir=/usr/share –includedir=/usr/include –bindir=/usr/bin –enable-safe-mode –with-config-file-path=/etc/php542 –enable-force-cgi-redirect –enable-discard-path –with-bz2 –enable-calendar –with-curl –enable-dbase –enable-exif –enable-ftp –with-gettext –with-gmp –with-iconv –with-ldap –with-libxml-dir=/usr/lib/ –enable-mbstring –with-mime_magic –with-mysql –with-mysqli –with-openssl –enable-pcntl –with-pcre-dir=/usr/lib/ –with-pdo_mysql –with-pdo_sqlite –with-readline –enable-shmop –enable-sockets –with-SQLite –enable-wddx –with-xsl –enable-zip –with-zlib

# Changes from what php -m spits out. You don’t need the info below in your phpconfigure.sh script
#–enable-calendar
#–with-ctype # default
#–with-date # not found, default?
#–enable-dbase
#–with-dom # default
#–enable-exif
#–with-filter #default
#–with-ftp
#–with-hash #default
#–with-json #default
#–with-libxml-dir=/usr/lib/
#–enable-mbstring
#–with-memcache #not found, default?
#–enable-pcntl
#–with-pcre-dir=/usr/lib/
#–with-PDO #taken care of with the pdo_mysql and pdo_sqlite
#–with-Reflection #default
#–with-session #default
#–enable-shmop
#–with-SimpleXML #default
#–enable-sockets
#–with-SPL #default
#–with-standard #not found, is it SPL? default?
#–with-tokenizer #default
#–enable-wddx
#–with-xdebug #not found, not needed
#–with-xml #default
#–with-xmlreader #default
#–with-xmlwriter #default
#–enable-zip
#–with-Xdebug #not found, not needed

[/code]

NOTE: make sure you do not include ‘–with-apxs2=/usr/sbin/apxs’. This is what installs PHP as an Apache module. Also, since you have the original PHP running, you can theoretically make a phpinfo file (with phpinfo() ) in it, and grab the configure entries from that, making sure to change ‘–with-config-file-path=/etc’ ‘–with-config-file-scan-dir=/etc/php.d’

During the configure, you might run into some errors. Again from the php.net comment:

The previous yum command should take care of most of those dependencies.

After the phpconfigure script runs without errors, then simply run

As the JpGraph tutorial explains, there is no need to run “make install”. Just simply copy the php-cgi executable to the proper place. We’ll get to that step shortly.

Set up Apache VirtualHost and website directories

Now you need to create two directories to handle the PHP as CGI. They can be virtually wherever, but should be in the same directory where you have the main html content. So if you set the path to the website data (in the httpd.conf) to /path/to/htdocs/, then you’ll need to make a /path/to/php524/ and a /path/to/php524-cgi/

and

After you have those directories, you can add the VirtualHost information to the Apache config (httpd.conf). I like to have a separate file for the VirtualHosts, so I added this to the end of the httpd.conf file.

And to allow VirtualHosts, uncomment this line:

To allow Apache to listen on (or accept requests from) different ports besides the default 80, add another Listen line to the httpd.conf file:

I used port 8524 to correspond to version 5.2.4 of PHP

Now create the XXXXX_vhosts.conf file

[code lang=”bash”]
#this doesn’t really seem to be needed, but it’s there
NameVirtualHost *:8524

# this is the original and runs the PHP as a module

DocumentRoot /path/to/htdocs/
ServerName somesite.org

####### Add other Virtual Hosts below here #######

# Setup PHP 5.2.4 on port 8524

DocumentRoot /path/to/php524/
# We use a separate CGI directory
ScriptAlias /cgi-bin/ /path/to/php524-cgi/

# These are the two critical statements for this virtual
# host. This activates PHP 5.2.4 as a CGI module
Action php524-cgi /cgi-bin/php-cgi
AddHandler php524-cgi .php5 .php

#Options None
Options FollowSymLinks
#AllowOverride None
AllowOverride All
Order allow,deny
Allow from all
# For good measure we also add recognition of PHP5 index
DirectoryIndex index.html index.php index.php5

[/code]

Now, you need to copy the php-cgi binary/executable to the /path/to/php524-cgi/ directory. The php-cgi file is located in the file where you ran the configure and make for the new php install. So if you did all that in the /opt/php-5.2.4/ directory, the php-cgi will be located at /opt/php-5.2.4/sapi/cgi/php-cgi.

Finally, copy the php.ini file to the right place. And configure as needed.

Test the apache configs to make sure they work:

If that returns OK restart Apache.

You can make a phpinfo page to test that it’s using the new PHP version.
[code lang=”php”]
< ?php
phpinfo();
? >
[/code]
Then check out your new site: http://somesite.org:8524/phpinfo.php

In order to get the different versions of PHP to interact with MySQL, you’ll have to use the URL on port 80 as the MySQL host. So, for example, in a WordPress install at http://somesite.org:8524/blog, the wp-config.php will have to have the following for the MySQL hostname:

There is some issue with mod_rewrite on the different versions of PHP. I’ll replace this paragraph with a fix when I have one.
UPDATE: 9/9/09 – I figured out how to get the .htaccess working for the Omeka installs we were working with. I needed to change the AllowOverride lines in the vhost.conf (or httpd.conf) file from None, to All.

Well, there you go. Hope that’s enough detail to get you going.

Share and Enjoy:
  • Print
  • PDF
  • RSS

Related Posts:


4 thoughts on “Multiple PHP Instances With One Apache

  1. Matt

    I’m confused by the last part, your XXXXX_vhosts.conf file. First, you don’t include the opening and closing tags, shouldn’t these be in there somewhere? Also, the directories you instructed to create were:

    $ mkdir /path/to/php524/
    and
    $ mkdir /path/to/php524-cgi/

    However I don’t see /path/to/php524-cgi/ used in your configuration directives? Could you clarify?

    Great article, thanks.
    Matt

    1. ammon Post author

      Hi Matt,

      Glad this helped.

      Boy this was a long time ago. We don’t have this set up anymore, so I can’t go back and verify, but here’s my best guess as to what is up.

      The opening and closing tags should be in there. I added them as I think they should go.

      The ScriptAlias line should be the one pointing to /path/to/php524-cgi/.

      Thanks for catching those issues. I updated the post with those changes.

  2. Justin

    This post comes up within the first five results for a number of Google searches I did while trying to figure out how to configure multiple instances / versions of PHP on a single Apache server. The article is extremely well written and was very helpful, but by the time I finished with the configuration you suggest, I was puzzled by one thing.

    Why is it necessary to have the second instance run as CGI?

    Since you’re declaring a separate Action and Handler (php524-cgi in your case), would it not be possible to have both versions of php compiled with apxs, and running as Apache modules?

    Your handler, declared within the VirtualHost configuration, would direct Apache to use php524 for that particular Virtual Host, while another VirtualHost configuration would use the ‘default’ php module – which I assume in the example you give would be PHP 5.2.0 but could just as easily be PHP 5.3.x or PHP 5.4.x

    This would mean that it would be possible to run both instances as Apache modules and avoid the disadvantages associated with running PHP as CGI. Similarly, you could run both PHP versions as CGI and avoid the disadvantages of running as an Apache module – depending on your environment and what you’re trying to achieve.

    Any thoughts on this?

    I have yet to try this as my dev server now is operational with the configuration as suggested above, but I’d like to know if anyone has tried running two versions of PHP both as Apache modules.

    1. ammon Post author

      Great comment, Justin. I’m glad the tutorial was helpful. I think at the time I wanted to see how cgi and module would perform. I’m not sure if you can run PHP as two separate modules in Apache. I know multiple PHP as cgi is possible. I seem to remember Apache could only handle one PHP as module, but I bet it could be done with different PHP config and module files.

      If anyone does figure that out, please post back your findings.

Comments are closed.