Here is my little recipe for getting PHP4 and PHP5 to run concurrently on FreeBSD using Apache 2.2 and mod_proxy.
First, check this out:
https://web.archive.org/web/20040603011318/http://wiki.coggeshall.org/37.html
That’s the basic recipe, however there are a couple of problems with it. The first is what appears to be a syntax error (perhaps an incompatibility between 1.3 and 2.2 versions of Apache) that I fix later, the second is that this ProxyPass only does half the job! I found that, using this method, if i went to the PHP4 host, it displayed the correct index page, however if i put something like http://php4.myhost.com/subdir then it changed the URL of the browser to be http://127.0.0.1:8081/subdir! This wasn’t to do at all. Thanks to megapaz in the apache chatroom on freenode for pointing me to this next article (and thankyou to niq also for writing it!):
http://www.apachetutor.org/admin/reverseproxies
So I also need a reverse proxy. That article is really long and deals with the issue in great detail, more detail than I required. I do not need to deal with multimedia content, javascript links or problems with links in general because I am only using PHP4 to run one very specific application.
There is one specific upshot of this: the discussion below deals with compiling the proxy modules from the FreeBSD ports system, however when I tested it out, this did not include all the modules mentioned in the above article, so in order to get all those modules compiled in, you will need to look into which ‘KNOBS’ you can turn on (see below) or manually change the Makefile.
Compiling with mod_proxy from FreeBSD ports
Because when you install from a port in FreeBSD you don’t actually type ./configure, you have these things called ‘knobs’ that allow you to set/remove common options. In order to configure with mod_proxy when installing Apache 2.2 from the ports, I did this:
cd /usr/ports/www/apache22
make WITH_PROXY_MODULES=yes
make install
I then include the following lines up the top of httpd.conf (where I
have added line breaks for readability, they are marked with “\”):
LoadModule proxy_module libexec/apache22/mod_proxy.so
LoadModule proxy_connect_module libexec/apache22/ \
mod_proxy_connect.so
LoadModule proxy_http_module libexec/apache22/ \
mod_proxy_http.so
Installing another Apache instance
For this I just downloaded the latest version of Apache 2.2 from the apache.org website and cut and pasted the instructions in John Coggeshall’s tute above to install it without the ports.
PHP Installation
Now that I had Apache 2.2 installed from the ports, I went through my usual PHP5 installation for which I don’t actually use the ports. So I just get the latest from php.net and have a script called runconf.sh which has my configure line in it that I’ve been using forever:
#!/bin/sh
./configure --with-fastcgi --enable-versioning --with-xsl
--enable-xslt --with-curl --enable-memory-limit
--enable-memlimit -with-layout=GNU
--with-config-file-scan-dir=/usr/local/etc/php
--with-regex=php --with-openssl=/usr --with-openssl-dir=/usr
--with-apxs2=/usr/local/sbin/apxs --enable-debug
--enable-zend-multibyte --prefix=/usr/local
i386-portbld-freebsd5.4 --with-gd
--with-jpeg-dir=/usr/local/bin --with-zlib --with-mysql
--with-freetype-dir=/usr/local/lib/ --with-tidy
Once that was all up and running, I needed to install PHP4. So I downloaded the latest version of PHP4 from php.net, and used the following line in configure:
./configure --prefix=/usr/local/apache_php4/php4/
--exec-prefix=/usr/local/apache_php4/php4/
--with-apxs2=/usr/local/apache_php4/bin/apxs
So when I installed, my PHP4 installation was located in my second Apache installation folder. I then copied php.ini-recommended into:
/usr/local/apache_php4/php4/lib/
And downloaded the latest APC (Alternative PHP Cache). I wanted to install it for the PHP4 installation, so I followed the instructions in the INSTALL file, but used the phpize and php-config included in the php4 folder I had installed under my apache_php4 installation:
cd APC_DIR
/usr/local/apache_php4/php4/bin/phpize
./configure --enable-apc --enable-apc-mmap --with-apxs \
--with-php-config=/usr/local/apache_php4/php4/bin/php-config
If you haven’t used phpize on this machine before it will complain it can’t find autoconf etc. FreeBSD comes with autotools 253 and 259. I’ve found that 259 works for phpize, so I do:
cd /usr/local/bin
ln autoconf259 autoconf
ln autoheader259 autoheader
Configuring and running Apache
I won’t bother going through Apache configuration here, but there is a mistake on the Coggeshall wiki (well, for v2.2 it doesn’t work, perhaps it worked for 1.3 or something). I put a file called php4.conf in /usr/local/etc/apache22/Includes/ with the following in it:
<VirtualHost *:80>
Servername clv-php4.workingsoftware.com.au
DocumentRoot /dev/null
<Location />
ProxyPass http://127.0.0.1:8081/
ProxyPassReverse http://127.0.0.1:8081/
php_value error_log "/var/log/php/php4-error.log"
</Location>
</VirtualHost>
And use the ‘Listen’ directive explained in the Coggeshall wiki in the instance of Apache that is running PHP4.
I then run my Apache PHP5 instance as normal, and use the good old apachectl for the PHP4 instance:
/usr/local/etc/rc.d/apache22 start
/usr/local/apache_php4/bin/apachectl start
Bug 37770
After running for a few hours, I noticed that the Proxy would mysteriously stop working, and would return a 502 error page with the error:
proxy: error reading status line from remote server 127.0.0.1
This was a real doozy, as it was a very intermittent bug and didn’t seem to be related to load or anything in the code that was being executed. I tried running httperf on it to load test and could not reproduce the error reliably. After some reading, I found this blog post mentioning a similar error using mod_proxy to run Mongrel for Ruby on Rails hosting:
I also found this mentioned here:
http://httpd.apache.org/docs/2.0/mod/mod_proxy.html#envsettings
So from this I concluded that my VirtualHost include should now look like this:
<VirtualHost *:80>
Servername clv-php4.workingsoftware.com.au
DocumentRoot /dev/null
<Location />
ProxyPass http://127.0.0.1:8081/
ProxyPassReverse http://127.0.0.1:8081/
php_value error_log "/var/log/php/php4-error.log"
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
</Location>
</VirtualHost>
I then restarted both the PHP5 and PHP4 Apache instances:
/usr/local/apache_php4/bin/apachectl restart
/usr/local/etc/rc.d/apache22 restart
and I am yet to see the error recur having run the system for nearly 48 hours since doing it. If the error does recur I’ll update my post but it appears to be fixed.
That’s it! Now I can point my browser to http://php4.myhost.com/ and it serves up pages using PHP4, but maintains the correct domain in the browsers URL bar. Because I’ve used a VirtualHost directive to pass to the PHP4 instance, I can easily make any domain I’d like get served up with PHP4.