Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ntopulos/3a492b3279f575d8ad4ddbea57e7d1bd to your computer and use it in GitHub Desktop.
Save ntopulos/3a492b3279f575d8ad4ddbea57e7d1bd to your computer and use it in GitHub Desktop.
Steps to get multiple versions of PHP running alongside on separate Apache virtual hosts using phpfarm

Multiple PHP versions on Ubuntu 16.04

Steps to get multiple versions of PHP running alongside on separate Apache virtual hosts using phpfarm.
The guide uses the example of PHP v5.4.45 and v7.0.7, but installation of any version and any number of versions will be done this same way.

Prerequisites

Update the machine:

apt-get update
apt-get upgrade

Install compilation tools:

apt-get install build-essential

If it is not already there, install a LAMP server:

apt-get install lamp-server^

Install phpfarm

cd /opt
git clone git://git.code.sf.net/p/phpfarm/code phpfarm

Configure PHP

Before compiling any PHP version, setup the options you need. Options can be global or php-version specific.
In my case I will install php-5.4.45 and php-7.0.7, each with its own configuration.

cd /opt/phpfarm/src
cp options.sh custom-options-5.4.45.sh
cp options.sh custom-options-7.0.7.sh
nano /opt/phpfarm/src/options.sh

Example of my custom-options-5.4.45.sh:

#!/bin/bash
# You can override config options very easily.
# Just create a custom options file; it may be version specific:
# - custom-options.sh
# - custom-options-5.sh
# - custom-options-5.3.sh
# - custom-options-5.3.1.sh
#
# Don't touch this file here - it would prevent you to just "svn up"
# your phpfarm source code.

version=$1
vmajor=$2
vminor=$3
vpatch=$4

#gcov='--enable-gcov'
configoptions="\
--enable-bcmath \
--with-mysqli \
--with-curl \
--with-png \
--with-gd \
--enable-gd-native-ttf \
--enable-calendar \
--enable-exif \
--enable-ftp \
--enable-mbstring \
--enable-pcntl \
--enable-soap \
--with-pdo-mysql \
--enable-sockets \
--enable-sqlite-utf8 \
--enable-wddx \
--enable-zip \
--with-openssl \
--with-jpeg-dir=/usr/lib \
--with-png-dir=/usr/lib \
--with-freetype-dir=/urs/lib \
--with-zlib \
--with-gettext \
--with-mcrypt \
--with-bz2 \
--with-mysql=/usr \
$gcov"

echo $version $vmajor $vminor $vpatch

Note that the last extension refers to mysql, which does not exist for php-7.

To configure php.ini:

cp default-custom-php.ini custom-php.ini

My looks like this:

upload_max_filesize=300M
post_max_size=300M
max_file_uploads=100

date.timezone=Europe/Zurich
include_path=".:/opt/phpfarm/inst/php-$version/pear/php/"

Compile each PHP version

Illustration with php-5.4.45:

cd /opt/phpfarm/src
./compile.sh 5.4.45

The compilation will probably fail, because we lack some libraries for requested extensions.

Here are the packages corresponding to the above configuration:

apt-get install libxml2-dev libssl-dev libcurl4-openssl-dev pkg-config libbz2-dev libjpeg-dev libpng12-dev libmcrypt-dev libmysqlclient-dev

If you still get errors or if you use another configuration, here is a more exhaustive error-extensions list: #Errors encountered while trying to compile PHP7 from source

To verify the installation:

cd /opt/phpfarm/inst/bin
./php-5.4.45 --version

Notes:

  • Compilation requires a machine with more than 512 MB of RAM; it worked with 2GB.
  • To recompile a second time a php version, you have to first remove the related folders from /opt/phpfarm/inst/bin.

Install and enable FastCGI

Run:

apt-get install libapache2-mod-fastcgi apache2-suexec-pristine
a2enmod actions fastcgi suexec
service apache2 restart

Add these lines to /etc/apache2/apache2.conf before the includes:

# FastCGI configuration for multiple PHP versions
FastCgiServer /var/www/cgi-bin/php-cgi-5.4.45
FastCgiServer /var/www/cgi-bin/php-cgi-7.0.7
ScriptAlias /cgi-bin-php/ /var/www/cgi-bin/

Create the cgi directory:

mkdir /var/www/cgi-bin

Then create a cgi file for each php version. Here the /var/www/cgi-bin/php-cgi-5.4.45:

#!/bin/sh
PHPRC="/etc/php5/cgi/5.4.45/"
export PHPRC

PHP_FCGI_CHILDREN=3
export PHP_FCGI_CHILDREN

PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS

exec /opt/phpfarm/inst/bin/php-cgi-5.4.45

Make the file executable:

chmod +x /var/www/cgi-bin/php-cgi-5.4.45

Create virtual hosts

Create a config file for each virtual host, e.g.:

nano /etc/apache2/sites-available/example.local.conf
<VirtualHost *:80>
	ServerName example.local
	DocumentRoot /var/www/example.local/public/
	<Directory "/var/www/example.local">
		AddHandler php-cgi .php
		Action php-cgi /cgi-bin-php/php-cgi-5.4.45
		<FilesMatch "\.php$">
			SetHandler php-cgi
		</FilesMatch>
	</Directory>
</VirtualHost>

Do not forget to create the corresponding directories and their index files.

Enable the site:

a2ensite example.local.conf

Comment out the last line of the IfModule block in /etc/apache2/mods-available/fastcgi.conf:

<IfModule mod_fastcgi.c>
	AddHandler fastcgi-script .fcgi
	#FastCgiWrapper /usr/lib/apahce2/suexec
	#FastCgiIpcDir /var/lib/apache2/fastcgi
</IfModule>

Reload Apache configuration and restart the service:

service apache2 reload
service apache2 restart

Your hosts should now be accessible.

If you work on a local machine, do not forget to add the domain to /etc/hosts:

127.0.0.1 example.local
@bartek5186
Copy link

Hello, what mean this "PHPRC="/etc/php5/cgi/5.4.45/"
we need have /etc/php5/cgi/... in system ?

@eikoni
Copy link

eikoni commented Oct 19, 2016

In a local server we have a 403 Forbidden :
You don't have permission to access /cgi-bin-php/php-cgi-5.5.6/index.php on this server

Test in CGI-BIN config :
/var/www/cgi-bin/php-cgi-5.5.6

#!/bin/sh
PHPRC="/opt/phpfarm/inst/php-5.5.6/lib/php.ini"

No issue.

We remove FilesMatch in :
/etc/apache2/sites-available/example.local.conf

<VirtualHost *:80>
    ServerName example.local
    DocumentRoot /var/www/htlm
    <Directory "/var/www/htlm">
        AddHandler php-cgi .php
        Action php-cgi /cgi-bin-php/php-cgi-5.5.6
        #<FilesMatch "\.php$">
            SetHandler php-cgi
        #</FilesMatch>
    </Directory>
</VirtualHost>

Return PHP 7.0 in browser...
Any update ?

@fandreotti
Copy link

When execute ./compile.sh 5.4.45 return error: Segmentation fault (core dumped)

@ScorchP
Copy link

ScorchP commented Dec 1, 2016

I only get a 500 Internal Server Error and this in the error log:

[Thu Dec 01 09:30:45.501711 2016] [fastcgi:error] [pid 8796] (13)Permission denied: [client X.X.X.X:38268] FastCGI: failed to connect to server "/var/www/cgi-bin/php-cgi-5.6.28": connect() failed
[Thu Dec 01 09:30:45.502687 2016] [fastcgi:error] [pid 8796] [client X.X.X.X:38268] FastCGI: incomplete headers (0 bytes) received from server "/var/www/cgi-bin/php-cgi-5.6.28"

@PaulMaas
Copy link

PaulMaas commented Jul 8, 2017

If you get a segmentation fault during compilation (like @fandreotti), it means that you need to remove the redundant code from after you copied options.sh to custom-options-*.sh cp options.sh custom-options-5.4.45.sh.

Basically, if you left the code at the bottom:

custom="custom-options.sh"
[ -f $custom ] && source "$custom" $version $vmajor $vminor $vpatch
custom="custom-options-$vmajor.sh"
[ -f $custom ] && source "$custom" $version $vmajor $vminor $vpatch
custom="custom-options-$vmajor.$vminor.sh"
[ -f $custom ] && source "$custom" $version $vmajor $vminor $vpatch
custom="custom-options-$vmajor.$vminor.$vpatch.sh"
[ -f $custom ] && source "$custom" $version $vmajor $vminor $vpatch

around, it would create an infinite loop. @ntopulos, you should probably add a line to your tutorial to note that. Took me a while to figure out, lol!

@rahulraveendran31
Copy link

The requested URL /cgi-bin-php/php53.fcgi/index.php was not found on this server.

I got the above error. Is it due to some permission issue?

@khasman
Copy link

khasman commented Mar 12, 2018

It has been successfully installed and when I check the php version it shows the default version pre installed in the system instead of 5.4.45 which I have installed using mentioned steps in given tutorial

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment