This document will help in installing multiple PHP versions on Arch Linux when you have PHP 5.4 or the latest PHP installed through Pacman.
PHP 5.4 is the default version available in Arch Linux’s repositories. If your PHP applications do not work properly with PHP 5.4, e.g., for Drupal 7 as of now, you would need PHP 5.3. There is a PHP5.3 build in the AUR, but I’ve personally found building PHP5.3 from source is more sustainable and can be better customized to your needs.
This setup uses PHP-FPM and Nginx as mentioned in the Arch Wiki page for Nginx. It can be extended to cover multiple different PHP versions operating simultaneously.
For this piece, we will cover installing PHP 5.3.26, currently the “old stable” release of PHP. Here is how I did it:
Overview
There are three main steps involved in installing multiple PHP versions:
-
Compile PHP from source,
-
Configure PHP-FPM and PHP-FPM’s systemd script, and
-
Configure Nginx to use the newly installed PHP-FPM’s connection socket.
Prerequisites
PHP 5.3.26 complete source code can be downloaded in either tar.bz2 or in tar.gz format from the PHP downloads page.
Compiling PHP from source needs automake, autoconf, libtool, re2c, flex, bison, along with an ANSI C compiler and any custom modules like GD etc installed as mentioned here. For Arch Linux, the base-devel
package provides most of these tools. The rest need to be installed manually. Assuming MySQL/Mariadb, GD library etc are installed, the build toolchain can be installed using:
# pacman -S base-devel re2c
Compile PHP
Extract the archive and proceed with configure. Let us assume the archive has been extracted to ~/build/php/php-5.3.26/
. We have two important considerations here:
-
We will need to provide a custom
--prefix
path to PHP so that the new version is installed in a separate directory so that it doesn’t interfere with existing PHP versions. -
To make our compiled version of PHP work with PHP-FPM, we shall need to configure it with the
--enable-fpm
flag.
For this example, we will install PHP 5.3.26 to /usr/local/php/php5.3.26
. Also, I need MySQL, cURL, mbstring for my development. So here is the configure command I used:
$ ./configure
–prefix=/usr/local/php/php5.3.26
–with-zlib-dir
–with-freetype-dir
–enable-mbstring
–with-libxml-dir=/usr
–enable-soap
–enable-calendar
–with-curl
–with-mcrypt
–with-zlib
–with-gd
–disable-rpath
–enable-inline-optimization
–with-bz2
–with-zlib
–enable-sockets
–enable-sysvsem
–enable-sysvshm
–enable-pcntl
–enable-mbregex
–with-mhash
–enable-zip
–with-pcre-regex
–with-mysql
–with-pdo-mysql
–with-mysqli
–with-jpeg-dir=/usr
–with-png-dir=/usr
–enable-gd-native-ttf
–with-openssl
–with-fpm-user=http
–with-fpm-group=http
–enable-ftp
–with-gettext
–enable-fpm
Note that, on my local setup, I do not need IMAP, Kerberos etc. If you need those, go ahead and add the configure flags.
After that, do the actual compiling:
$ make
The only reason the compile would fail at this point is if you do not have a library installed but some of the configure flags need them. If the build succeeds, and if you have loads of time on your hands, run a build test using make test
. Otherwise install the code:
$ sudo make install
PHP should now be installed to /usr/local/php/php5.3.26
and the PHP5.3.26 binary should be available at /usr/local/php/php5.3.26/bin/php
. Try the following and see if it gives you proper version output:
$ /usr/local/php/php5.3.26/bin/php --version
For easy access to the PHP 5.3.26 binary from command line, symlink to it from the /usr/bin
directory:
$ sudo ln -s /usr/local/php/php5.3.26/bin/php /usr/bin/php5.3
Now you should be able to call $ php5.3 --version
and get the same result. To check if the original PHP installation through pacman is intact, run $ php --version
and see the difference.
Next, we need to copy over a php.ini
file to the lib
subdirectory. PHP ships with a development and a production sample of php.ini
. You can find them in your build directory, that is where you had extracted the files and ran the compile. Taking our example, and using the development sample, do:
$ sudo cp -v ~/build/php/php-5.3.26/php.ini-development /usr/local/php/php5.3.26/lib/php.ini
Edit this php.ini and change the values as necessary.
Configure PHP-FPM
The PHP-FPM binary is installed in the sbin
directory. Let us symlink it as well to have it available on the path:
$ sudo ln -s /usr/local/php/php5.3.26/sbin/php-fpm /usr/bin/php-fpm5.3
Run PHP-FPM’s version to ensure it has been properly linked:
$ php-fpm5.3 --version
Next, create a custom PHP-FPM configuration in the etc
directory. PHP provides a sample config file that we can use:
$ cd /usr/local/php/php5.3.26
$ sudo cp etc/php-fpm.conf.default etc/php-fpm.conf
Edit etc/php-fpm.conf
and modify the following information:
-
In
[global]
hangepid
to/run/php-fpm/php-fpm5.3.pid
-
Change
syslog.ident
tophp-fpm5.3
-
Change
user
andgroup
tohttp
-
Change
listen
to/run/php-fpm/php-fpm5.3.sock
. Using UNIX sockets are always faster than TCP sockets. Nginx will connect to this socket.
Assign ownership /run/php-fpm
to http
:
$ sudo chown -R http:http /run/php-fpm
Configure systemd scripts to start PHP-FPM 5.3
Create a new file, /etc/systemd/system/php-fpm5.3.service
and add the following information:
[Unit]
Description=The PHP 5.3 FastCGI Process Manager
After=syslog.target network.target
[Service]
Type=forking
PIDFile=/run/php-fpm/php-fpm5.3.pid
PrivateTmp=true
ExecStart=/usr/bin/php-fpm5.3 --pid /run/php-fpm/php-fpm5.3.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
I have used Type=forking
to let php-fpm fork happily in the background. The PIDFile keeps track of the process generated. Using Type=notify
as Arch’s PHP 5.4’s PHP-FPM does resulted in timeouts when starting the service.
Next, try starting the php-fpm5.3.service and see if the PHP-FPM process has started:
$ sudo systemctl daemon-reload
$ sudo systemctl start php-fpm5.3.service
$ sudo systemctl status php-fpm5.3.service
Two files, “php-fpm5.3.pid” and “php-fpm5.3.sock” should be generated in /run/php-fpm
when the service has started. To make the PHP-FPM 5.3 service load on reboots, do $ sudo systemctl enable php-fpm5.3.service
.
Configure Nginx
You should already have Nginx configured by now, and if you had used Arch Linux Wiki’s steps, you would have a Location
block in Nginx’s config file. We need to tell Nginx to use php-fpm5.3’s socket instead of original php-fpm’s socket.
So, replace fastcgi_pass
in:
location ~ .php$ {
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
with:
location ~ .php$ {
fastcgi_pass unix:/run/php-fpm/php-fpm5.3.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
Save configuration and restart Nginx. After restart, Nginx should process PHP scripts for that site using PHP 5.3 instead of PHP 5.4. Other sites would continue using PHP 5.4.
That’s all!
Tip
To avoid changing the path to PHP-FPM each time you have some change, you can set an upstream
in the http
of the default nginx.conf
:
# Upstream connection to php-fpm unix socket
upstream php {
server unix:/run/php-fpm/php-fpm.sock;
}
# Upstream connection to php-fpm5.3 unix socket
upstream php5.3 {
server unix:/run/php-fpm/php-fpm5.3.sock;
}
Now, edit the site’s Nginx configuration file and modify fastcg_pass
to:
fastcgi_pass php5.3
For an app running on PHP 5.4, change it to:
fastcgi_pass php
Now even if you have a thousand site configurations, updating PHP-FPM path is easy by simply editing the upstream
in nginx.conf
!