LAMP 2019LinuxOpen SourcePHP

PHP – Building a LAMP Server (2019)

This is the eighth article in a series on building the ultimate LAMP Server. This covers installing PHP from source so you can run multiple versions and easily switch between them.

Estimated time (this post only): 1 to 4 hours
* varies depending on how much you install

Warning: this article is a work in progress and incomplete. This warning will be removed once it is done.


Why FPM?

The simplest way to install PHP is as an Apache module. However, this limits you to a single version of PHP. Installing as a CGI script allows you to run multiple versions easily. FastCGI is a better-performing implementation of CGI. FPM is a process manager to manage the FastCGI Server API for PHP. Different web hosts use different methods of managing multiple versions of PHP. Here are the two most common scenarios:

  • Offer each supported version of PHP as a CGI and/or FastCGI script. This is what I recommend.
  • Offer a default installation of PHP as a module for better performance and other versions as CGI/FastCGI scripts. This used to be the preferred method, but with the advances in server hardware, this is no longer as common.

Prerequisites

Assuming you’ve downloaded all the prerequisites mentioned previously, you shouldn’t need any other packages. The PHP Group maintains extensive documentation on their website. You can read it for more details. But if you’ve been following this guide, you should already have most everything you need for most (if not all) extensions I’m covering here.

Create a user for FPM to use:

sudo useradd -rU php

For PostgreSQL support, you may need to do the following:

sudo ln -s /usr/pgsql-11/ /usr/local/pgsql

Download Source

You should test against the supported versions listed on the PHP Download Site. As of this writing, they have stopped releasing even security updates for PHP 7.0 and older. By the end of this year support will also be dropped for 7.1. If you need to develop for older versions of PHP, you can find them on the PHP Releases page.

The latest statistics from W3Techs show that the following are the most popular server-side scripting languages/versions (those with over 5% market share): PHP 5.6 (24.4%), 5.4 (10.7%), 5.3 (8.9%), 7.0 (8.6%), 7.2 (7.4%), 5.5 (7.3%), and 7.1 (6.7%). As you can see, despite support being dropped for PHP 5 and 7.0, they still are the most popular, so you should probably develop for them as well as the current versions.

Important: PHP 5 with openSSL support will not build properly on some distributions. Downgrading openSSL will solve the problem but I highly recommend against it. I tested some proposed patches, but most either compromised security or only worked on specific distros. I encountered many other issues which required a lot of workarounds on other distributions. If you want to build PHP 5 you should stick to something like CentOS or an older version of Ubuntu. But even those will probably have issues soon. It is time to start transitioning to PHP 7, but many web hosts have been slow adopting it as their default version (though most provide it). You should use the 7.2 branch at this time while testing against the newer versions to ensure future compatibility. I have chosen this year not to release custom patches like I did in the past as I feel it only encourages developers and web hosts to support software which is outdated and not secure.

That being said, 5.6 is the most-used version right now, and the following will download it (but without a lot of work will not install under Fedora, Ubuntu, or most other distros as of this writing).

TMPVER="5.6.40" && TMPINSTNAME="php56"
cd ~
wget --no-check-certificate -O php-${TMPVER}.tar.bz2 \
http://us.php.net/get/php-${TMPVER}.tar.bz2/from/this/mirror

Other versions you can try as of this date:

TMPVER="7.0.33" && TMPINSTNAME="php70"
TMPVER="7.1.28" && TMPINSTNAME="php71"
TMPVER="7.2.17" && TMPINSTNAME="php72"
TMPVER="7.3.4" && TMPINSTNAME="php73"

Verify the download against the sha256 checksum shown on the download page if desired:

sha256sum php-${TMPVER}.tar.bz2

Assuming the download is valid, extract it:

tar xvjf php-${TMPVER}.tar.bz2

Configure PHP

Depending on your requirements you may not wish to use the same options as below. Read this entire section before executing the following commands.

The following should be compatible with most PHP installations on shared hosts and provides support for PDO, MySQL/MariaDB, SQLite, and PostgreSQL (I put the database extensions last so you can remove anything you don’t need).

mkdir ~/php-$TMPVER/bld
cd ~/php-$TMPVER/bld

../configure --prefix=/opt/$TMPINSTNAME --datadir=/opt/$TMPINSTNAME/share \
--localstatedir=/opt/$TMPINSTNAME/var --with-libdir=lib64 --without-pear  \
--enable-cgi --enable-fpm --enable-bcmath=shared --with-bz2=shared \
--enable-calendar=shared --enable-ctype=shared --with-curl=shared \
--enable-dom=shared --enable-exif=shared --enable-fileinfo=shared \
--enable-filter=shared --with-freetype-dir=/usr --enable-ftp=shared \
--with-gd=shared --with-gettext=shared --with-gmp=shared --enable-hash \
--with-iconv=shared --with-imap=shared --with-imap-ssl --enable-intl=shared \
--with-jpeg-dir=/usr --enable-json=shared --with-kerberos \
--enable-libxml=shared --enable-mbregex --enable-mbregex-backtrack \
--enable-mbstring --with-mcrypt=shared --with-mhash=shared --enable-opcache \
--with-openssl=shared --enable-pcntl=shared --with-pspell=shared \
--with-pcre-regex --enable-phar=shared --with-png-dir=/usr \
--enable-posix=shared --with-readline=shared --enable-session=shared \
--enable-shmop=shared --enable-simplexml=shared --enable-soap=shared \
--enable-sockets=shared --enable-sysvmsg=shared --enable-sysvsem=shared \
--enable-sysvshm=shared --with-tidy=shared --enable-tokenizer=shared \
--enable-wddx=shared --enable-xml=shared --with-xmlrpc=shared \
--enable-xmlreader=shared --with-xsl=shared --enable-xmlwriter=shared \
--with-xpm-dir=/usr --enable-zip=shared --with-zlib=shared --with-zlib-dir=/usr \
--enable-pdo \
--with-mysqli=shared,mysqlnd --with-pdo-mysql=shared,mysqlnd \
--with-sqlite3 --with-pdo-sqlite \
--with-pdo-pgsql=shared --with-pgsql=shared

If anything goes wrong in the configure or make process below, do the following before running configure again:

make clean
rm -rf *

Configure For Other Databases

The following should should be added to the configure line for the other databases covered in the previous article as necessary (change paths as needed).

For Oracle:

--with-oci8=shared --with-pdo-oci=shared,/opt/oracle/product/18c/dbhomeXE

For MS-SQL:

--with-mssql=shared --with-pdo-odbc=shared,unixODBC,/usr

The DB2 extensions must be installed via PECL, which will be covered later on.

For SAP ASE:

--with-mssql=shared --with-pdo-dblib=shared

For Firebird:

--with-interbase=shared,/opt/firebird --with-pdo-firebird=shared,/opt/firebird

Install PHP

If all went well, you can now run make:

make
make test

The test phase will take a while. I have tried to avoid as many errors as possible, but you probably will still encounter a few. To minimize errors, start all databases you have compiled PHP for. Many database tests will still fail since you set custom passwords and install directories. Older versions of PHP may have bugged test scripts and sometimes the failures can be avoided by copying the updated scripts from the latest version of PHP. If you want to be thorough you can save the test output to a text file and go through each failed test result by appending the last line with something like > ~/phptest.log.

Now install:

sudo make install

Create a default php.ini file. You can choose between the development and production versions. The biggest difference is error reporting. With the development version, PHP errors will appear in your web browser. It’s unsafe to do this on any production system as it exposes PHP code to the public, but can be useful on a development machine. So run only one of the following commands as desired.

sudo cp ~/php-$TMPVER/php.ini-development /opt/$TMPINSTNAME/lib/php.ini
sudo cp ~/php-$TMPVER/php.ini-production /opt/$TMPINSTNAME/lib/php.ini

Make a default php-fpm.conf file:

sudo cp /opt/$TMPINSTNAME/etc/php-fpm.conf.default \
/opt/$TMPINSTNAME/etc/php-fpm.conf
sudo mkdir /opt/$TMPINSTNAME/etc/fpm.d
sudo nano /opt/$TMPINSTNAME/etc/php-fpm.conf

Change a few things in this file. First, un-comment the following lines (remove the semicolon at the beginning):

include=etc/fpm.d/*.conf
pid = run/php-fpm.pid

Next edit the following line:

listen = 127.0.0.1:9000

Change this to listen on a socket rather than a TCP port. Both methods have their advantages in terms of performance and security. If you stick with ports, each PHP instance has to be unique. Sockets are easier and arguably more secure:

listen = var/run/php.sock

You will see three lines that start with "listen." These determine the owner and permissions of the socket we set above. The default values won’t work because Apache isn’t running as the same user as PHP (your browser will return a 503 error). Assuming you are using the default values for Apache (you can check these in "httpd.conf"), un-comment and edit these three lines as follows:

listen.owner = daemon
listen.group = daemon
listen.mode = 0660

Further down the file, find and un-comment "security.limit_extensions". For example:

security.limit_extensions = .php .php3 .php4 .php5

After saving that file, you also need to edit the Apache configuration:

sudo nano /opt/apache/conf/httpd.conf

Un-comment the following lines and save the file:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

Do some cleanup:

cd ~
rm php-${TMPVER}.tar.bz2
sudo mv php-$TMPVER /usr/local/src/

Leave a Reply

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