Running multiple instances of Apache

by Arnold Daniels on 03/26/2007

Life as a shared hosting provider hasn’t become easier after PHP decided that they would allow compatibility breakage between mayor versions. Some providers managed to keep there customers satisfied while only supporting PHP 4, but lots of new projects are PHP 5 only and the problem will become even bigger when PHP 6 is released.

Usually a daemon (a service for you windows folks) is started once, with only one instance running. The same goes for Apache. However when we look closely at the apache config, we see that variables which prevent apache from being started twice, the pid file, lockfile and ip/port, can be configured. When starting apache, the config file can be specified, which allows to run multiple instances of apache (on different ip’s).

Now we can simply change the IP address of a domain in the DNS, to switch is from PHP 4 to PHP 5. The same trick can also be used easily switch the plan of an account from basic (only static html pages) to gold (php and perl support) to platinum (php, perl, ruby and jsp support), without having to move the account to another server.

Back to PHP, lets go trough the steps of setting up the server to run PHP 4 next to PHP 5.

NOTE: This tutorial assumes you are working on an Ubuntu or Debian linux system.


Step 1 – Building php

First we need build PHP 4 and PHP 5 in a way that the paths and filenames won’t conflict. I won’t go into details about building PHP, but you will need to add the following to configure for PHP 5:

./configure
'--libdir=/usr/lib/php5' \
'--includedir=/usr/include/php5' \
'--program-suffix=5' \
'--with-exec-dir=/usr/lib/php5/libexec' \
'--with-config-file-path=/etc/php5/'




Step 2 – Create additional apache configuration files

Because all instances will have more of less the same configuration we will include apache2.conf for the common configuration and use a macro to setup the differences. If you haven’t installed mod-macro already, please install it (apt-get install libapache2-mod-macro) and enable it (a2enmod macro).

We want to specify the IP-address per instance, so please remove the content of /etc/apache2/ports.conf. Also remove the symlinks of all modules that should not be loaded in all instances (like php5_module) from /etc/apache2/mods-enabled.

Create a file called /etc/apache2/apache2-instance.macro and enter your per instance configuration, eg:

<Macro SetupInstance $instance $ip>
LockFile /var/lock/apache2/$instance.accept.lock
PidFile /var/run/apache2/$instance.pid
ErrorLog /var/log/apache2/$instance/error.log
Listen $ip:80
</Macro>

Create apache2-php4.conf:

Include /etc/apache2/apache2.conf
Include /etc/apache2/apache2-instance.macro
Use SetupInstance "apache2-php4" "192.168.1.50"
LoadModule php4_module /usr/lib/apache2/modules/libphp4.so
<IfModule mod_php4.c>
AddType application/x-httpd-php .php .phtml .php3
AddType application/x-httpd-php-source .phps
</IfModule>

Also create apache2-php5.conf. Do not forget to create /var/log/apache2/apache2-php4 and /var/log/apache2/apache2-php5.


Step 3 – Changing the scripts


When you run ‘apache2ctl start’, the script will display “no listening sockets available, shutting down” and exit. This is expected, though we do want to start apache, so we need to change the script.
Copy the /usr/sbin/apache2ctl to /usr/sbin/apache2-php4ctl and /usr/sbin/apache2-php5ctl. Edit apache2-php4ctl and change HTTPD to

HTTPD='/usr/sbin/apache2 -f /etc/apache2/apache2-php4/apache2.conf'

Do the same for apache2-php5.

There’s another script that has to be changed, which is located in /etc/init.d. Copy /etc/init.d/apache2 to /etc/init.d/apache2-php4 and /etc/init.d/apache2-php5 and move the file to /etc/init.d/apache2.org.

Edit /etc/init.d/apache2-php4 and set

APACHE2CTL="$ENV /usr/sbin/apache2-php4ctl"

The script tries to find the PID by getting the name of the pidfile from the config, but that won’t work because we’re using a macro. So simply set

PIDFILE='/var/run/apache2/apache2-php4.pid'
if [ -e "$PIDFILE" ] ; then
PID=`cat "$PIDFILE"`
fi

Comment out everything from ‘for i in $AP_CONF’ to ‘done’. Make the same changes for /etc/init.d/apache2-php5.

Last create a new /etc/init.d/apache2 script (mind the execute privs) with the following content:

#!/bin/sh
./apache2-php4 $@
./apache2-php5 $@




Conclusion

Simply restart your server and you’re up and running. You might want to stray a bit from this example to match your own configuration, but anyhow I hope this have given you some ideas.

Arnold Daniels

I've spend a big part of my life behind a computer, learning about databases (MySQL), programming (PHP) and system administration (Linux). Currently I playing with HTML5, jquery and node.js.

More Posts

Follow Me:
TwitterLinkedIn

There are 13 comments in this article:

  1. 20 July 2007Justin Kestelyn says:

    Great post – can I interest you in writing an expanded version for publication by OTN?

    ReplyReply
  2. 1 August 2007bandesz says:

    Great post, agreed, but there are small mistakes:
    – missing / at the closing tag of
    – I had to manually enable mod-macro in /etc/apache2/mods-enabled (debian)
    – a space is missing (after copy&paste) between [ and - (dash) here: if [-e "$PIDFILE" ] ; then
    – the file name and the content of the necessary modifications aren’t matching when modification of /etc/init.d/apache2-php4 is described

    Thank You for the useful tip!

    Cheers!

    ReplyReply
  3. 1 August 2007Arnold Daniels says:

    Thank you bandesz. I’ve corrected the article accordantly.

    ReplyReply
  4. 21 August 2007DM says:

    Thanx for article, Arnold.

    Sorry for my poor English ;)
    But why not to use one version of PHP as module and the others (php5, php6) as cgi? On the hosting such approach will give even more security, cause in such manner you could execute php-scripts with privileges of selected user.
    Or cgi approach has some disadvantages compared to module? (sure, except time needed for loading interpreter at first request)

    ReplyReply
  5. 22 August 2007Arnold Daniels says:

    Well that’s it basically. If PHP is running as CGI, each page requests uses an additional process. This has heavy consequences on the load of the system (mem, CPU), impacting the performance and limiting the number of accounts per server (ca 30% in our tests).

    If you have security in mind, you should suid the Apache process and not only the CGI process (mpm-itk or perchild). That is, if you want don’t disable .htaccess files and we don’t want to do that. For your information, we didn’t really like the performance impact of itk, so we run a custom module which does the switching.

    ReplyReply
  6. 2 September 2007Arnold Daniels says:

    Catch this article in French at http://g-rossolini.developpez.com/tutoriels/logiciels/plusieurs-apache-simultanes

    ReplyReply
  7. 19 October 2007Paul Tipper says:

    Arnold,

    Is it possible to run 2 instances of Apache using the same IP address but on different ports?

    ReplyReply
  8. 19 October 2007Arnold Daniels says:

    Hi Paul,
    A short answer: Yes.

    ReplyReply
  9. 3 November 2007Elroy says:

    Hi Arnold,

    do you think it is possible to run parallel instances of Apache 2 and Apache 2.2 on a windows machine (different ports of course)?

    ReplyReply
  10. 3 November 2007Arnold Daniels says:

    I haven’t got any experience with Apache on Windows. Please read this article to see if it applies to your situation.

    http://www.emphasisdevelopment.com/wp/12-2005/switching-between-multiple-php-versions-usimg-apache-on-windows/

    ReplyReply
  11. 10 December 2007Andreas Kaiser says:

    Great tutorial. Just what I needed for my server.

    But I’m having some problems. I allways get the “no listening sockets available, shutting down” when using apache2 -k start

    When I use “apache2-php5ctl” (or “apache2-php4ctl”) the pid file is created and the server works.

    But when using “apache2 -k stop” I get error: “httpd (no pid file) not running”, when using “apache2-php5ctl stop” the server is stopped.

    I think I have made something wrong in “/etc/init.d/apache2-php5″

    Note: I can’t find “for i in $AP_CONF” in my apache2-php5 file

    ReplyReply
  12. 10 April 2008Golan says:

    Sweet nifty little example. Gonna give it a try, but seems pretty straightforward.
    דירות בגולן

    ReplyReply
  13. 29 October 2009olivier pare says:

    Thanks, smart usage of mod_macro.

    The next step (for security) would be to execute php scripts as differents users, as it can be done with suexec + php-cgi. MPM ITK permits this using mod_php.

    I am thinking at a combination with your trick : ITK + multiples mod_php could be a fine production shared hosting, isn’t it ? Has somebody ever tried ?

    Regards,

    ReplyReply

Write a comment: