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:

https://web.archive.org/web/20061107212446/http://blog.pomozov.info/posts/apache-mongrel-and-proxy-error.html

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.