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:
<br />
./configure<br />
'--libdir=/usr/lib/php5' \<br />
'--includedir=/usr/include/php5' \<br />
'--program-suffix=5' \<br />
'--with-exec-dir=/usr/lib/php5/libexec' \<br />
'--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:
<br />
<Macro SetupInstance $instance $ip><br />
LockFile /var/lock/apache2/$instance.accept.lock<br />
PidFile /var/run/apache2/$instance.pid<br />
ErrorLog /var/log/apache2/$instance/error.log<br />
Listen $ip:80<br />
</Macro><br />
Create apache2-php4.conf:
<br />
Include /etc/apache2/apache2.conf<br />
Include /etc/apache2/apache2-instance.macro<br />
Use SetupInstance "apache2-php4" "192.168.1.50"<br />
<br />
LoadModule php4_module /usr/lib/apache2/modules/libphp4.so<br />
<IfModule mod_php4.c><br />
AddType application/x-httpd-php .php .phtml .php3<br />
AddType application/x-httpd-php-source .phps<br />
</IfModule><br />
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'<br />
if [ -e "$PIDFILE" ] ; then<br />
PID=`cat "$PIDFILE"`<br />
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:
<br />
#!/bin/sh<br />
./apache2-php4 $@<br />
./apache2-php5 $@<br />
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.


Great post – can I interest you in writing an expanded version for publication by OTN?
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!
Thank you bandesz. I’ve corrected the article accordantly.
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)
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.
Catch this article in French at http://g-rossolini.developpez.com/tutoriels/logiciels/plusieurs-apache-simultanes
Arnold,
Is it possible to run 2 instances of Apache using the same IP address but on different ports?
Hi Paul,
A short answer: Yes.
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)?
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/
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
Sweet nifty little example. Gonna give it a try, but seems pretty straightforward.
דירות בגולן
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,