Tom Cannaerts

Run multiple versions of PHP using fcgid and suexec

When hosting multiple sites on the same server, you sometimes might just want to be able to run different versions of PHP. Add multiple users to the problem (like in a typical shared hosting environment) and you probably might also want to prevent a user from accessing files of another user. You may also want to make it a lot easier to track down the website with that buggy script that’s using up all server resources. It will involve compiling your own PHP versions, but overall it’s actually less scary than it looks. Even if you don’t care about multiple versions of PHP, you can still use this guide to set up PHP to run under the users account instead of the apache user.

To get started, you will need to have apache2 installed, together with mod_fcgid and suexec. You can do so with your favorite package manager. Since I’m using debian, apt is my weapon of choice.

apt-get install apache2 apache2-suexec libapache2-mod-fcgid

After installing, make sure that the actions, suexec and fcgid module are enabled in the apache config.

a2enmod actions
a2enmod suexec
a2enmod fcgid

Now it’s time to get started on the PHP versions you would like. Download the PHP source files of the PHP versions you which to install. In this example, I’ll be installing PHP 5.3.21 and PHP 5.4.11. The key to compiling the PHP, is to make sure it is suitable to run as CGI/FCGI/FastCGI. You can do this by compiling the PHP without the Apache Extentions (apxs) by simply leaving out the –with-apxs parameter in the configure statement. Since you are compiling PHP yourself, you will need to specify the modules you want to include. If you haven’t compiled PHP before, you might just want to do some more reading on that. If you are installing multiple versions of PHP, you will want to specify the path where the PHP need to be installed using the prefix parameter. This allows you to have each version in it’s own folder with a clear name, instead of /usr/local/lib/php. If you are compiling PHP 5.2, you will need to add the –with-fastcgi option to the configure script, for PHP 5.3 and above this is already implied.

tar -xjvf php-5.3.21.tar.bz2
cd php-5.3.21
./configure –prefix=/usr/local/lib/php-5.3.21 –with…. <your custom config options go here>
make && make install

After compilation (this can take a while), you will end up with your PHP binaries in the folder you specified. In my case that was /usr/local/lib/php-5.3.21 and /usr/local/lib/php-5.4.11.

The next step in the process is to create the users that we want the websites to run under. To keep it simple, I created two users, php53user and php54user. For each user, I created a directory structure for the website:

mkdir /var/www/php53user/
mkdir /var/www/php53user/fcgi/
mkdir /var/www/php53user/htdocs/

In the fcgi folder, create a script called php-wrapper (can have any name) which will call the actual PHP binary. As you will be creating such file for every website, you can choose the desired PHP version by calling the appropriate binary.

#!/bin/sh
exec /usr/local/lib/php-5.3.21/bin/php-cgi

Since we are going to be running through suexec, permissions on the folders and files need to be correct for this to work.

# base folder
chown -R php53user:php53user /var/www/php53user
chmod -R 755 /var/www/php53user

#fcgi script
chmod 700 /var/www/php53user/fcgi/php-wrapper

# htdocs folder, apache needs read+execute access
chown php53user:www-data /var/www/htdocs
chmod 750 /var/www/php53user/htdocs

Now that we have our PHP versions compiled, users created and directory structure in place, we just need to configure our vhosts

<VirtualHost *:80>
ServerName php53.tom.be
ServerAdmin webmaster@localhost
SuexecUserGroup php53user php53user
DocumentRoot /var/www/php53user/htdocs
<Directory /var/www/php53user/htdocs>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
                AddHandler fcgid-script .php
                Options +ExecCGI +FollowSymLinks
                FcgidWrapper /var/www/php53user/fcgi/php-wrapper .php
</Directory>
LogLevel warn
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
</VirtualHost>

The SuexecUserGroup line will instruct apache to run the processes under the php53user user and group. The AddHandler will map .php files to fcgid, and the FcgidWapper will tell it to use our wrapper script.

Restart apache. You now have a vhost running under it’s own user, using the PHP version you want.

phpinfo screenshot

Finally, if you would like to use a different php.ini file for each website, you can do that by adding the -c parameter in the wrapper script when calling the PHP binary.

#!/bin/sh
exec /usr/local/lib/php-5.3.21/bin/php-cgi -c /var/www/php53user/fcgi/my-custom-php.ini

When running htop, you can clearly see it in action:

htop screenshot

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.