Backward compatibility testing can be a bit of a drag. The actual testing may be straightforward, but setting up the environment often is not. A little while ago I have put a PHP app through its paces on Apache 1.3 with PHP 5.2. Apache 1.3 still accounts for about 5% of Apache installations out there. If an app is distributed directly to end users, perhaps on shared hosting, a market share of 5% is reason enough to make it work on old Apache, or at least give it a shot.
Current distros don't offer support for Apache 1.3, and haven't done so for ages. So here are my notes for setting up a reusable test system in a VM. I've also thrown in a recipe for setting up Java 6, which involves a bit of fiddling in a legacy OS. With Java 6 installed, even PhpStorm can be run in the stone-age VM.
Content Overview
As a base, I picked Ubuntu 6.06 Dapper because there still is an Apache 1.3 package for it. Later Ubuntu releases just provide Apache 2.
Previously, I had tried Ubuntu 10.04 Lucid, compiling Apache from source. That seemed like a good idea at first because Lucid provides a more modern environment. But I ran into some weird, buggy behaviour with mod_rewrite after a while, and finally abandoned Lucid in favour of stone-age Dapper. There is no point in running a test environment which is buggy in itself.
While Apache 1.3 is more stable in Dapper, there is a tradeoff. Current virtualization software doesn't guarantee support for guests as old as this. I'm still on VMWare Workstation 7, which is fine for Dapper, but upon arrival of the current Workstation 9, it has dropped from the compatibility list. If you are on version 9 or don't use VMWare at all, VirtualBox is your best bet. It supports Dapper, but be aware that there may be boot crashes once in a while. And one more thing: the VM must be maintained manually. A Dapper setup can't be managed with modern tools like Vagrant or Puppet.
Setting up the OS is mostly standard fare. I just took the Dapper ISO file and created the VM. Here are some things to watch out for:
https://old-releases.ubuntu.com/ubuntu/
. The URL issue can be fixed quickly, e.g. in Synaptic (Settings -> Repositories) or by editing sources.list. Change the URLs and enable all repos, including dappper-backports.apt-get install apache
or Synaptic. Test Apache localhost.sudo apt-get install linux-headers-$(uname -r)
and reinstalling the VMWare Tools. VirtualBox might need a similar procedure.AddDefaultCharset UTF-8
to the Apache configuration. Otherwise, non-ASCII characters in UTF-8 encoding will end up garbled in the browser. This is likely to happen because UTF-8 encoding is pretty much the default these days.Apache 1.3 has this to tell after successful installation:
/etc/apache
./var/www
./usr/lib/cgi-bin
, which is where Debian packages will place their scripts./var/log/apache
, and will be rotated weekly. The frequency of rotation can be changed by editing /etc/logrotate.d/apache
.index.html
, meaning that requests for a directory /foo/bar/ will give the contents of the file /var/www/foo/bar/index.html if it exists (assuming that /var/www is your DocumentRoot).public_html
directory of the users' homes. These dirs should be under /home
, and users will not be able to symlink to files they don't own.All the standard apache modules are available with this release and are managed with apache-modconf. Type sudo apache-modconf apache enable <module_name>
to enable additional modules. Many other modules are available through the package system with the names libapache-mod-*
. If you need to compile a module yourself, you will need to install the apache-dev
package.
Talking about modules, the command apache -l
will list the modules which are compiled in with Apache. A complete list of loaded modules is revealed by cat /etc/apache/modules.conf
.
PHP 5.2 is a good baseline for testing backwards compatibility. Older versions of PHP 5 never gained much traction.
In Dapper, though, there aren't any ready-made packages for PHP 5.2. Official support by the distro ended with PHP 5.1. Backporting is not an option, either: PHP 5.2 packages for later Ubuntu releases are made for Apache 2. So PHP 5.2 for Apache 1.3 needs to be built from source. Here's how.
build-essential
package first.libxml2-dbg
, libxml2-dev
and libmysqlclient15-dev
.sudo mkdir -p /etc/php5/apache
.sudo mv php.ini-recommended /etc/php5/apache/php.ini
.Build and compile:
./configure --enable-force-cgi-redirect --with-config-file-path=/etc/php5/apache --with-mysql
make
sudo make install
Additional PHP modules can be enabled by adding the appropriate option to the configure
directive (e.g --enable-exif
).
Adjust the Apache config. This can be done by creating a 'php-cgi.conf' file in /etc/apache/conf.d/ with the following content:
ScriptAlias /local-bin /usr/local/bin
AddHandler application/x-httpd-php5 php
Action application/x-httpd-php5 /local-bin/php-cgi
The Action
command in the previous step requires mod_actions. Enable it with sudo apache-modconf apache enable mod_actions
. By the way, there is no need to enable mod-actions for other, non-CGI flavours of PHP (which I'll cover next).
sudo apachectl restart
.Additional Resources
Instead of installing PHP as a CGI program, it can be set up as an apache module which is loaded dynamically (as opposed to being compiled into Apache statically). Most of the steps are identical to the ones above. Just the configure options are different. And unlike the CGI version, it doesn't require changing the Apache configuration. So here goes:
build-essential
, libxml2-dbg
, libxml2-dev
and libmysqlclient15-dev
.sudo mkdir -p /etc/php5/apache
) and copy the php.ini file (sudo mv php.ini-recommended /etc/php5/apache/php.ini
). Nothing new up to this point.apache-dev
package.which apxs | head -n1
.Build and compile:
./configure --with-apxs=[your apxs path here] --with-config-file-path=/etc/php5/apache --with-mysql
make
sudo make install
Just as with the CGI version, additional PHP modules can be enabled by adding the appropriate option to the configure
directive (e.g --enable-exif
).
If everything went according to plan, the build process will report back with the following file layout info:
Installing PHP CGI binary: /usr/local/bin/ [when installing CGI or FCGI]
Installing PHP CLI binary: /usr/local/bin/
Installing PHP CLI man page: /usr/local/man/man1/
Installing build environment: /usr/local/lib/php/build/
Installing header files: /usr/local/include/php/
Installing helper programs: /usr/local/bin/
Installing PEAR environment: /usr/local/lib/php/
Wrote PEAR system config file at: /usr/local/etc/pear.conf
You may want to add: /usr/local/lib/php to your php.ini include_path
Installing PDO headers: /usr/local/include/php/ext/pdo/
The php.ini file is stored in /etc/php5/apache
.
I haven't done it. It is a bit more involved than the two methods above. If you have a particular reason to go down that route, here's what I've got.
--with-apache[=DIR]
. DIR is the top-level Apache build directory, defaults to /usr/local/apache
. There is more to it - see the additional resources below.libapache-mod-fastcgi
and then build PHP with --enable-fastcgi
. Setting it up in Apache can be a bit tricky. See Google for details ;)Additional Resources
Apache and PHP are up and running now. Let's add some testing tools. First of all, we need to get PEAR up to speed.
sudo pear upgrade PEAR
sudo pear update-channels
sudo pear upgrade-all
Installing PHPUnit is next. The last version suitable for PHP 5.2 is PHPUnit 3.6.12. If things worked as they should, a plain pear install pear.phpunit.de/PHPUnit-3.6.12
would do the trick. But the automatic process for installing the PHPUnit dependencies is broken, and you'll end up with error messages when trying to run PHPUnit. The commands below download the dependencies with explicit version numbers, guaranteeing a working setup.
sudo pear config-set auto_discover 1
sudo pear install pear.phpunit.de/File_Iterator-1.3.2
sudo pear install pear.phpunit.de/Text_Template-1.1.2
sudo pear install pear.phpunit.de/PHP_Timer-1.0.3
sudo pear install pear.symfony-project.com/YAML-1.0.6
sudo pear install pear.phpunit.de/PHP_TokenStream-1.1.4
sudo pear install pear.phpunit.de/PHP_CodeCoverage-1.1.3
sudo pear install pear.phpunit.de/PHPUnit_MockObject-1.1.1
sudo pear install pear.phpunit.de/PHPUnit-3.6.12
Important: It is impossible to lock down PHPUnit and keep it at a certain version for good. This is unfortunate because a single command is enough to mess it up. Specifically, don't run pear upgrade-all
beyond this point, ever. It will break your PHPUnit setup. Should that happen, you need to uninstall each of the packages above individually. Then reinstall as described.
Luckily, setting up XDebug is more straightforward:
sudo apt-get install autoconf
sudo pecl install xdebug
The output will show the path to the XDebug module (xdebug.so), something along the lines of /usr/local/lib/php/extensions/no-debug-non-zts-20060613/xdebug.so
. Add it to php.ini with the directive zend_extension="/{absolute path to module}/xdebug.so"
. Don't use the line "extension=xdebug.so", contrary to what the PECL installer tells you. That may work for other kinds of PECL installs, but it doesn't work for XDebug.
Finally, add your XDebug config to php.ini as you normally would - presumably, at least xdebug.remote_enable = 1
and an appropriate xdebug.remote_host
setting.
This step is very, very optional indeed. Still, to me it was helpful to have a current IDE around in the VM, and I went with PhpStorm.
Installing PhpStorm is straightforward once Java is set up properly. Getting Java installed is somewhat less straightforward, though. The procedure below follows the tips provided on "ask ubuntu".
First off, don't use Java 7 for Dapper, it will cause you no end of grief. Instead go with the latest JDK 6, available here. Download the JDK 6 .bin file and set permissions to "executable". Then open a terminal in the download directory and execute the file:
$ ./jdk-6u34-linux-x64.bin
The JDK is now extracted to a directory of the same name. (Your .bin file and directory might be named slightly differently from the one I used, of course, depending on which release of Java is current by the time you read this).
Next, rename the directory to java-6-oracle, then move it to /usr/lib/jvm.
$ mv jdk1.6.0_34 java-6-oracle
$ sudo mv java-6-oracle /usr/lib/jvm
Finally, download and run an install script, switching to the new JVM. I have to say it didn't work for me. I ran into error messages, so I went with the manual install (see option 2, below).
$ wget https://webupd8.googlecode.com/files/update-java-0.5b
$ chmod +x update-java-0.5b
$ sudo ./update-java-0.5b
You may need to select the newly installed Java (again) with
$ sudo update-alternatives --config java
Verify with
$ java -version
$ javac -version
Return values should identify Java version "1.6.0_34".
If update-java-0.5b complains about an illegal update-alternatives
option, do the job of the script manually. Just follow another answer on "ask ubuntu" by doing this:
$ sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/java-6-oracle/bin/java" 1
$ sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/java-6-oracle/bin/javac" 1
$ sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/java-6-oracle/bin/javaws" 1
and then select the right versions with
$ sudo update-alternatives --config java
$ sudo update-alternatives --config javac
$ sudo update-alternatives --config javaws
Again, verify the result with
$ java -version
$ javac -version
returning a version of "1.6.0_34".
Done. :)