Update (Oct 1, 2011): The release notes for the newest version of Amazon’s Linux (2011.09) state that “PHP scripts have the option of using PHP-FPM.” PHP-FPM is now included in the amzn-main repository, and can be installed via
yum install php-fpm (it is installed to /usr/sbin).
As a point of mention, if you want to use ‘php-fpm’ without apache (e.g. with nginx), do not install the package ‘php’, but only php-fpm. The php package installs mod_php, which, being an apache module needs apache. For instance, my standard install is:
yum install php-fpm php-bcmath php-gd php-mbstring php-mcrypt php-mysql php-pdo php-pecl-apc php-tidy php-xml php-xmlrpc php-imap php-intl
The basis for the init script (for PHP 5.3.6) is available from the PHP source. Modify prefix, exec_prefix, php_fpm_BIN, php_fpm_CONF, and php_fpm_PID. Also ensure your php-fpm.conf file (located in /etc) is setup correctly.
I found that I was getting a blank page when loading php files. This resulted from the default
nginx.conf file having the root directives set inside the location blocks instead of directly under the main server block. As such, the $document_root variable was incorrectly set in the php block (but the request was passed to php-fpm). Unfortunately, neither the nginx nor php-fpm error logs showed anything (even when set to the debug/info levels). Once the
fastcgi_param SCRIPT_FILENAME is set correctly, it is probably a good idea to set the
fastcgi_intercept_errors directive to
on (otherwise 404 errors on the php-fpm side will yield the aforementioned blank page, which is unlikely to be the expected outcome).
Original article (mostly obsoleted by the update):
I have been running Amazon’s Linux distribution on my EC2 instances for some time now, and have consistently been pleased with it. It has a low memory footprint, and has been stripped of many unnecessary components. Furthermore, I expect that Amazon has optimized the distribution for their EC2 platform, and in terms of performance, it would certainly appear to be the case.
Amazon provides its own repository (amzn) for use with this distribution, and has been quite good at keeping it up to date and adding new packages. One package currently missing that is rather difficult to replace is the PHP FastCGI Process Manager (php-fpm), which has been bundled with PHP since v5.3.3. While it is possible to obtain this specific package from other repositories, invariably the dependencies require installing all of PHP from those repositories. Since I would like to continue using the amzn repository (and actually try not to add any others), I provide below the steps necessary to generate the full set of PHP RPMs, including php-fpm on Amazon’s Linux, using Remi Collet’s spec files which are available on GitHub.
PHP-FPM provides some distinct advantages over the typical FastCGI, including daemonization, adaptive process spawning, and different uids (like suPHP). It also works with Nginx a popular light weight webserver.
To start, we need the ‘Development Tools’ so we can compile and build the RPMs. (Installing these are not recommended on a production machine.)
yum groupinstall "Development Tools"
We will need to download some files, so I am going to use /usr/local/src as my working directory.
The command above downloads all of Remi’s spec and configuration files, and we now extract them:
tar -xzvf remicollet-remirepo-*.tar.gz
We will now copy the files to the SOURCES directory, and change to that directory:
cp remicollet-remirepo-*/php/* /usr/src/rpm/SOURCES/ cd /usr/src/rpm/SOURCES/
To build PHP there are quite a few dependencies we must satisfy. For the most part, these are development headers that we need to compile PHP against other packages.
Most of the dependencies are available in the amzn repository, and we will install them with yum.
yum install -y bzip2-devel curl-devel db4-devel gmp-devel httpd-devel pam-devel openssl-devel sqlite-devel zlib-devel libedit-devel krb5-devel libc-client-devel cyrus-sasl-devel openldap-devel mysql-devel postgresql-devel unixODBC-devel libxml2-devel net-snmp-devel libxslt-devel libxml2-devel libjpeg-devel libpng-devel freetype-devel xorg-x11-devel libmcrypt-devel libtidy-devel freetds-devel aspell-devel recode-devel libicu-devel libXpm-devel t1lib-devel pcre-devel libtool-ltdl-devel libevent-devel
There are a few other packages that Remi’s spec file requires, specifically sqlite2 and recode, which we can install as below.
Install the GPG Keys for the EPEL and Remi repositories:
rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi rpm --import http://download.fedora.redhat.com/pub/epel/RPM-GPG-KEY-EPEL
Download and install sqlite2 and recode, as well the development headers:
yum install http://rpms.famillecollet.com/enterprise/6/remi/x86_64/sqlite2-devel-2.8.17-5.el6.remi.x86_64.rpm http://rpms.famillecollet.com/enterprise/6/remi/x86_64/sqlite2-2.8.17-5.el6.remi.x86_64.rpm http://download.fedora.redhat.com/pub/epel/5/x86_64/recode-devel-3.6-24.el5.x86_64.rpm http://download.fedora.redhat.com/pub/epel/5/x86_64/recode-3.6-24.el5.x86_64.rpm
We need to make a few modifications to the spec file, in order for things to work:
add: %global rhel 6 set: with_enchant 0 set: runselftest 0
The items above let the compiler know that we are running something akin to RHEL 6. We also disable the Enchant spelling library, and turn off the self-tests (they increase the compile time significantly).
Before building, a few quick comments. On a t1.micro instance, it took 9 hours to compile plus 3 hours for tests (load average typically 1.15, with ~99% CPU usage), so I would suggest a larger instance for this. The c1.medium would be ideally suited to compiling (best price/performance) however, it is a 32-bit only platform (and compiling the 64-bit RPMs would require a bit of extra work). I decided to try for something a bit faster than half a day, and went with a c1.xlarge instance. The compiling task did not appear to fully utilize the 20 ECUs of the c1.xlarge instance (load avg peaked at 5). Given this, the m1.large may offer better price/perforance. Spot instances are definitely the way to go for this kind of task. On the c1.xlarge, I needed 10 minutes of prep time (editing files, etc), and the total compile took under 10 minutes.
Finally, we build:
rpmbuild -ba php.spec
When done, you will have a complete set of PHP RPMs, that are compatible with the amzn repository. For me, I ended up with the following (PHP 5.3.6):
For a common install (with php-fpm), consider the following (we need the –nogpgcheck since we have not signed the RPMs):
yum install --nogpgcheck php-5.3.6-4.amzn1.x86_64.rpm php-bcmath-5.3.6-4.amzn1.x86_64.rpm php-cli-5.3.6-4.amzn1.x86_64.rpm php-common-5.3.6-4.amzn1.x86_64.rpm php-fpm-5.3.6-4.amzn1.x86_64.rpm php-gd-5.3.6-4.amzn1.x86_64.rpm php-mbstring-5.3.6-4.amzn1.x86_64.rpm php-mcrypt-5.3.6-4.amzn1.x86_64.rpm php-mysql-5.3.6-4.amzn1.x86_64.rpm php-pdo-5.3.6-4.amzn1.x86_64.rpm php-soap-5.3.6-4.amzn1.x86_64.rpm php-sqlite-5.3.6-4.amzn1.x86_64.rpm php-tidy-5.3.6-4.amzn1.x86_64.rpm php-xml-5.3.6-4.amzn1.x86_64.rpm php-xmlrpc-5.3.6-4.amzn1.x86_64.rpm php-imap-5.3.6-4.amzn1.x86_64.rpm php-intl-5.3.6-4.amzn1.x86_64.rpm
If you run the above on another machine, remember that you will need to install sqlite2 before you can use php-sqlite.
You can, of course, also install other PHP packages using Remi’s spec files (again, adding ‘%global rhel 6’ to them), for instance, APC or suhosin.
Once you have php-fpm installed, you will want to edit the php-fpm.conf file as per http://php-fpm.org/wiki/Configuration_File and start php-fpm (the init script should have been installed):
service php-fpm start