Like many others, I was quite excited to see PHP 5.3 come out and immediately wanted to start using it. Unfortunately reality set in in the form of legacy sites running 5.2 (or older) and the need to maintain them. My solution is to have multiple versions of PHP running which can be configured on a per virtual host basis, specifically PHP 5.2.10 & 5.3 with Apache 2.2.12 and MySQL 5.1.36. I compiled the software on a Mac, but the instructions should work with little or no modification on most *nix flavors.
Disclaimer: This is what my dev setup is on my local machines (MBP & Mac Pro) and what works for me. I make no guarantees that this will work for you or that you won’t ruin your OS doing this.
Prerequisites
Since we are compiling from source, we’re gonna need gcc and make among other programs. They can all be downloaded for free with the Apple Developer Tools.
I like putting what I compile in a parent directory “/opt” for clarity and to not affect any built in OS X files. To do this:
sudo mkdir -p /opt/src sudo chmod g+w /opt/src cd /opt/src
Wget is going to be used to retrieve tarballs without having to leave the command line. It’s quite simple to install and will get your feet wet if you’ve never compiled software from source before. To install wget, you’re gonna have to download via browser the first time.
Download: http://ftp.gnu.org/gnu/wget/wget-latest.tar.bz2
Then in Terminal:
cp ~/Downloads/wget-latest.tar.bz2 . tar xvjf wget-latest.tar.bz2 cd wget-1.11.4/ ./configure --prefix=/opt make sudo make install
Remaining steps from here will be done via Terminal.
Now we want to add /opt/bin to our PATH so we don’t have to type it out every time. Open up ‘~/.profile’ with your favorite text editor *cough*VI*cough* and prepend it to the variable. In my case it looks like this:
export PATH="/opt/bin:$PATH"
Finally source the file to apply the changes:
. ~/.profile
You only have to this once. Next time you open Terminal it will be sourced automatically.
Still with me? Then on to…
Installing MySQL
Download and install:
cd /opt/src wget http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.36.tar.gz/from/http://mysql.he.net/ tar xvzf mysql-5.1.36.tar.gz cd mysql-5.1.36 CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \ CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" \ ./configure --prefix=/opt/mysql \ --localstatedir=/opt/mysql/data \ --with-extra-charsets=complex \ --enable-thread-safe-client \ --enable-local-infile \ --enable-assembler \ --with-mysqld-ldflags=-all-static \ --with-plugins=innobase make sudo make install
Create some symlinks from /opt/bin to MySQL’s bin:
sudo ln -s /opt/mysql/bin/* /opt/bin/.
Initialize the system tables and run it for the first time:
sudo mysql_install_db --user=mysql sudo mysqld_safe --user=mysql --log &
SECURE THE ROOT ACCOUNT AND REMOVE ANONYMOUS ACCESS:
mysql -u root
mysql> delete from mysql.user where User != 'root';
mysql> update mysql.user set Password=PASSWORD('supersecretpassword') where User='root';
mysql> flush privileges;
mysql> exit
Now you should need the password to connect as root, and anonymous access should be disabled.
Installing Apache
Download and install:
cd /opt/src wget http://apache.mirror.facebook.net/httpd/httpd-2.2.12.tar.bz2 tar xvjf httpd-2.2.12.tar.bz2 cd httpd-2.2.12 ./configure --prefix=/opt/apache2 \ --enable-mods-shared=all \ --enable-ssl \ --with-mpm=worker \ --enable-suexec \ --with-suexec-bin=/opt/apache2/bin \ --with-suexec-caller=_www \ --with-suexec-docroot=/projects make sudo make install sudo ln -s /opt/apache2/bin/* /opt/bin/.
We’ll come back to the Apache config after installing PHP.
Installing mod_fastcgi
Download and install:
cd /opt/src wget http://www.fastcgi.com/dist/mod_fastcgi-SNAP-0811090952.tar.gz tar xvzf mod_fastcgi-SNAP-0811090952.tar.gz cd mod_fastcgi-SNAP-0811090952.tar.gz cp Makefile.AP2 Makefile make top_dir=/opt/apache2 sudo make install top_dir=/opt/apache2
Create a tmp folder for FastCGI:
sudo mkdir -p /opt/tmp/fcgi sudo chmod -R 0777 /opt/tmp/fcgi
Create the config file for mod_fastcgi at “/opt/apache2/conf/extra/httpd-fastcgi.conf”:
LoadModule fastcgi_module modules/mod_fastcgi.so FastCgiIpcDir /opt/tmp/fcgi AddHandler fastcgi-script .fcgi FastCgiConfig -autoUpdate -singleThreshold 100 -killInterval 300 AddType application/x-httpd-php .php ScriptAlias /fastcgi/ /opt/apache2/cgi-bin/ <Directory "/opt/apache2/cgi-bin"> Options ExecCGI SetHandler fastcgi-script Order allow,deny Allow from all </Directory>
Install PHP 5.2.10
Download and install:
cd /opt/src wget http://us.php.net/get/php-5.2.10.tar.bz2/from/us2.php.net/mirror tar xvjf php-5.2.10.tar.bz2 cd php-5.2.10 ./configure --prefix=/opt/php5.2 \ --with-config-file-path=/opt/php5.2 \ --with-mysqli=/opt/bin/mysql_config \ --with-mysql=/opt/mysql \ --with-curl \ --enable-cli \ --enable-fastcgi \ --enable-discard-path \ --enable-force-cgi-redirect make sudo make install
Copy php.ini to your install dir:
sudo cp /opt/src/php-5.2.10/php.ini-dist /opt/php5.2/php.ini
Optional, but highly recommended. Open php.ini, change error_reporting to strict and turn magic quotes off:
error_reporting = E_ALL | E_STRICT magic_quotes_gpc = Off
Finally, create a PHP fcgi “wrapper” script at “/opt/apache2/cgi-bin/php52.fcgi” (you will have to use sudo):
#!/bin/sh PHP_FCGI_CHILDREN=1 export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=5000 export PHP_FCGI_MAX_REQUESTS exec /opt/php5.2/bin/php-cgi
Set the wrapper to be executable:
sudo chmod +x /opt/apache2/cgi-bin/php52.fcgi
Installing PHP 5.3
Download and install:
cd /opt/src wget http://us3.php.net/get/php-5.3.0.tar.bz2/from/us2.php.net/mirror tar xvjf php-5.3.0.tar.bz2 cd php-5.3.0 ./configure --prefix=/opt/php5.3 \ --with-config-file-path=/opt/php5.3 \ --with-curl \ --enable-cli \ --with-mysql=mysqlnd \ --with-mysqli=mysqlnd \ --with-pdo-mysql=mysqlnd make sudo make install
Copy over php.ini:
sudo cp /opt/src/php-5.3.0/php.ini-development /opt/php5.3/php.ini
And create the wrapped like we did for 5.2, but with a different name “/opt/apache2/cgi-bin/php53.fcgi”:
#!/bin/sh PHP_FCGI_CHILDREN=1 export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=5000 export PHP_FCGI_MAX_REQUESTS exec /opt/php5.3/bin/php-cgi
Lastly, make it executable:
sudo chmod +x /opt/apache2/cgi-bin/php53.fcgi
Tying it all together
Now we’ve got our MAMP2 stack ready to go, just need to setup our Apache config to use it.
Open up “/opt/apache2/conf/httpd.conf” and make the following changes:
- Change “User” and “Group” to “_www”
- Add index.php to “DirectoryIndex”. Should look something like “DirectoryIndex index.php index.html”
- Add permissions to your docroot. (I keep all my sites under “/projects”, just replace that with whatever you use, i.e. “/var/www”, “~/sites”):
<Directory "/projects"> Options Indexes FollowSymLinks AllowOverride All Order allow,deny Allow from all </Directory>
- Uncomment “Include conf/extra/httpd-vhosts.conf”
- Add “Include conf/extra/httpd-fastcgi.conf”
Set up virtual hosts. In “/opt/apache2/conf/extra/httpd-vhosts.conf”, delete everything below the “NameVirtualHost” directive and add:
<VirtualHost *:80> ServerAdmin you@domain.com DocumentRoot "/projects/site1" ServerName site1 ErrorLog "logs/site1-error_log" CustomLog "logs/site1-access_log" common Action application/x-httpd-php /fastcgi/php52.fcgi </VirtualHost> <VirtualHost *:80> ServerAdmin you@domain.com DocumentRoot "/projects/site2" ServerName site2 ErrorLog "logs/site2-error_log" CustomLog "logs/site2-access_log" common Action application/x-httpd-php /fastcgi/php53.fcgi </VirtualHost>
For testing purposes, let’s set up a simple PHP file in each VHost. For “site1″ the path to the file will be “/projects/site1/index.php” and look like this:
<h2>Site 1</h2> <?php phpinfo(); ?>
For “site2″ it will be at “/projects/site2/index.php” and look like this:
<h2>Site 2</h2> <?php phpinfo(); ?>
The last step is to set up your hosts file (sudo vim /etc/hosts) so you can get to the sites. Add the following entry
127.0.0.1 site1 site2
Now fire up your favorite browser and point it at “http://site1″ and “http://site2″ respectively. You should see something like this:
That’s it!
Please respond in the comments if you find any glaring errors or security issues, or just to say this helped!
Next post will be how to set up MySQL and Apache to start automatically via launchd.
References:
http://dev.mysql.com/doc/refman/5.1/en/index.html
http://httpd.apache.org/docs/2.2/
http://www.php.net/manual/en/
http://www.fastcgi.com/docs/faq.html
http://timdorr.com/archives/2006/02/php4-and-php4-s.php
