preload preload


The Perfect LAMP Stack – Apache2, FastCGI, PHP-FPM, APC

The Apache + mod_php combination has been ideal choice for most of peoples for their LAMP webserver. Easy to install and works most of the time make it favorite among the users. However, this setup is quite performance intensive and has some drawbacks which can be seen when the site grows in terms of users. Apache require more RAM to serve the requests whereas mod_php results in increased CPU cycles. The single user nature of PHP adds more complications because each user will have its own php process running on the webserver any time of request. Even the opcode caching solutions like APC, eAccelerator etc can’t be utilized to full extent because cache will be created for each user.

So, what could be ideal setup which can cover these issues? What and how we can install Apache, PHP and others which can provide good performance and remain stable even within high loads.

In the following guide, we will be using some best technologies and interweave them to make a perfect LAMP installation.

Note: May be some of you people advise me that Nginx installation can be much more efficient then the Apache one but I have made this setup because of certain modules which were only available with Apache and there were no alternatives in Nginx for them.

Let us begin now:

Required

1. Linux – The following installation instructions can be run over on all the linux flavors available today as we would be building everything from the source, However, FYI my webserver uses CentOS 5.3.

Learn More: The Advantages of Choosing Linux Webhosting

2. Apache2 HTTP server – Apache HTTP server has always been an industry standard webserver and been a first choice among the webhosting guys as a webserver solution. It is stable, easy to extend, customizable and efficient. We will be using Apache 2.2 for our perfect setup. You can obtain the latest version of Apache2 from http://httpd.apache.org/download.cgi

Learn More: Apache at your Web Service

3. FastCGI – FastCGI is just a variation of CGI interface which allows you to delegate your HTTP requests from webserver to the application. But the difference between FastCGI and CGI is that, the CGI is tied to the life of HTTP requests. CGI has to start and stop between each HTTP request cycle whereas using FastCGI, your application lives forever. The requests come from the HTTP server to FastCGI which only do the serving of response. With this architecture, a number of requests and responses can be served without loading the application every time.

In our setup, we will  use FastCGI module for the Apache HTTP webserver. You can download it from http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz

Learn More: FastCGI – The Forgotten Treasure

4. PHP-FPM – PHP-FPM is a recent alternative implementation of PHP with FastCGI. It is actually the patches over the PHP source and allows you to have built-in FastCGI process management right inside in PHP. As of now, PHP-FPM is about to go into the core of PHP project in 5.3.3 and is currently under development. So in our installation, we will patch the PHP 5.2 source with PHP-FPM patches.

We will be using PHP 5.2.13 source and PHP-FPM 0.5.14 patch. You can download PHP from http://www.php.net/get/php-5.2.13.tar.gz/from/a/mirror and PHP-FPM from http://php-fpm.org/downloads/php-5.2.13-fpm-0.5.14.diff.gz

Learn More: PHP-FPM Home

4. PHP-APC – The Alternative PHP Cache (APC) is the robust, fast and efficient way of optimizing and caching PHP intermediate code (opcode). We will finally use this one, as an improving performance alternative. We will use the stable version and you can grab it from http://pecl.php.net/get/APC-3.0.19.tgz

Learn More: PHP-APC Official Manual

Lets Roll it now

We will assume that you have already downloaded the required packages on you server. To confirm, there would be following archives on your system after downloading.

httpd-2.2.15.tar.gz
php-5.2.13.tar.gz
mod_fastcgi-current.tar.gz
php-5.2.13-fpm-0.5.4.diff.gz
APC-3.0.19.tgz

Compile Apache httpd server

Run the following commands to build Apache httpd server. The below commands will

1. Unzip the httpd-2.2.15.tar.gz archive.

2. The plain configure command will configure the Apache source with default settings based on your server configuration. If you require to install additional modules or parameters, please refer to Apache httpd documentation.

3. Finally make all install command will build the Apache httpd server on your server.

tar xvzf httpd-2.2.15.tar.gz
cd httpd-2.2.15
./configure
make all install

Compile mod_fastcgi module for Apache2

Apparently it is always advisable to install Apache modules as static objects, we will still be installing mod_fastcgi as a Dynamic Shared Object (DSO) for Apache2. I have tried hard to compile as a static library but failed to do so, so if anyone else was able to, please share with me.

Execute the following commands  to build mod_fastcgi for Apache2

tar xvzf mod_fastcgi-current.tar.gz
cd mod_fastcgi-2.4.6
apxs -o mod_fastcgi.so -c *.c
apxs -i -a -n fastcgi mod_fastcgi.so

Note: If you are unable to compile the module and getting errors, it is most likely that the apxs is not found. In that case please refer to exact path to apxs and then compile the module.

Compile PHP

Before building PHP, we would patch the PHP source with the PHP-FPM patches and will continue with the installation.

Execute the following commands

tar xvzf php-5.2.13.tar.gz
gzip -cd php-5.2.13-fpm-0.5.4.diff.gz | patch -d php-5.2.13 -p1
cd php-5.2.13
./configure --enable-fastcgi --enable-fpm --with-mysql=/var/lib/mysql --with-mysqlsock=var/lib/mysql/mysql.sock --with-zlib --with-zlib-dir --withgd --with-bz2 --enable-zip --with-curl=/usr/include --with-gettext --with-config-file-path=/usr/local/apache2/conf --enable-ftp --with-ttf --enable-mbstring --with-openssl --enable-soap --enableshmop --enable-sockets --with-pear=/usr/local/php --with-pdo-mysql --with-libdir=lib64 --with-png-dir --with-pcre-regex
make all install
cp php.ini-dist /usr/local/apache2/conf/php.ini

The above commands will patch the PHP source with PHP-FPM. If you notice, the configure command has two new parameters –enable-fastcgi and –enable-fpm. These parameters will enable the FastCGI process management in PHP. The other parameters are only for reference. You can add/remove any other parameter which you want to build with your PHP. If you get errors during the configure, it might be the reason that the dependency is not installed on your system. In that case, install the dependencies and rerun the configure command.

The last command will copy the PHP configuration file php.ini to the apache configuration directory and we have also referred to the same location during the compilation of PHP (–with-config-file-path=/usr/local/apache2/conf). The advantage of doing it is, all the configuration files are located at the same place on your webserver.

Compile APC

At the last, now we will build APC for our PHP setup. Run the following commands

tar xvzf APC-3.0.19.tgz
cd APC-3.0.19
phpize
./configure --enable-apc --enable-apc-mmap --with-apxs=/ usr/local/apache2/bin/apxs --with-php-config=/usr/local/bin/php-config
make
make install
cp modules/apc.so /usr/local/lib/php/extensions/apc.so

The phpize command will prepare the build environment for the PHP extension. To use APC with PHP on Apache requires the apxs for compilation. At the end, we copied the apc.so extension to the PHP extensions location. The same path is referred in php.ini file against extension_dir directive. If it is any other in your case, you can copy the apc.so to that location.

Finishing the job

So far we are complete with the installation of required components for our LAMP stack. Now we will configure the settings for them and will be done.

Following are the required configuration files which we will be editing:

/usr/local/apache2/conf/httpd.conf
/usr/local/apache2/conf/php.ini
/usr/local/etc/php-fpm.conf

httpd.conf changes

The following parameters should exists in httpd.conf to make Apache aware about FastCGI and PHP-FPM

User apache
Group apache

LoadModule fastcgi_module modules/mod_fastcgi.so

<IfModule mod_fastcgi.c>
ScriptAlias /fcgi-bin/ "/usr/local/apache2/fcgi-bin/"
FastCGIExternalServer /usr/local/apache2/fcgi-bin/php-cgi -host 127.0.0.1:9000 –pass-header Authorization
AddHandler php-fastcgi .php
Action php-fastcgi /fcgi-bin/php-cgi
</IfModule>

In the above configurations, LoadModule directive would include the mod_fastcgi module into the Apache. The <IfModule> wrapper can also be located in /usr/local/apache2/conf/extra/httpd-vhosts.conf. The settings inside <IfModule> will be explained at the end of the post.

php-fpm.conf changes

Following directives should be present and uncommented in php-fpm.conf file


<value name="owner">apache</value>
<value name="group">apache</value>
<value name="mode">0644</value>
<value name="user">apache</value>
<value name="group">apache</value>

Create a folder fcgi-bin inside /usr/local/apache2 folder and copy the php-cgi from /usr/local/bin to that location

mkdir /usr/local/apache2/fcgi-bin
cp /usr/local/bin/php-cgi /usr/local/apache2/fcgi-bin/
chown -R apache: /usr/local/apache2/fcgi-bin
chmod -R 755 /usr/local/apache2/fcgi-bin

What we have done above is, copied the php-cgi executable into fcgi-bin folder so that the PHP application can use it for processing the HTTP requests coming to the application.

In the <IfModule> wrapper earlier we have created ScriptAlias to the fcgi-bin folder so that the PHP applications can refer to it. We are using FastCGIExternalServer to dispatch the request coming to Apache HTTP server to PHP FastCGI server running on 127.0.0.1 and port 9000. The request dispatched would be processed by php-cgi. The next two lines of AddHandler and Action defines that only the requests of php scripts should be dispatched to the FastCGI server and not the requests of any other file formats such as images or javascripts or css.

The PHP-FPM configurations enforce that the process spawned due the requests coming to PHP FastCGI server should be accessed only by apache user or group. This is a good security model because it would not allow external user to access internal resources through PHP scripts.

Now, we can start our server and let it serve our applications efficiently.

php-fpm start
/usr/local/apache2/bin/apachectl start

To share some details, the above setup has given a performance improvement of around 150% for a complex Zend Framework application which we were running in a setup of two application servers with one dedicated MySQL server and one hardware load balancer. I hope this can benefit you too.

If you had any questions, please feel free to ask.

Liked the content? Then why not share with your pals

  • 10 responses to "The Perfect LAMP Stack – Apache2, FastCGI, PHP-FPM, APC"

  • ford lover
    15:58 on July 29th, 2010

    Being a blogger is like being in charge of your own personal insane asylum.

  • Deepesh
    10:29 on July 31st, 2010

    And wont that is awesome :P

  • Anonymous
    11:08 on December 14th, 2010

    It seems you have used the Apache 1.3 install instructions for mod_fastcgi. INSTALL.AP2 in mod_fastcgi dir contains install instructions for Apache 2.x:
    # cd mod_fastcgi-2.4.6
    # cp Makefile.AP2 Makefile
    # make ; make install

  • frntn
    2:13 on September 19th, 2011

    I had an error when trying to install fastcgi module with your command above :

    Warning! dlname not found in /lamp/apache/app/modules/mod_fastcgi.lo.
    Assuming installing a .so rather than a libtool archive.
    chmod 755 /lamp/apache/app/modules/mod_fastcgi.so
    chmod: cannot access `/lamp/apache/app/modules/mod_fastcgi.so': No such file or directory
    apxs:Error: Command failed with rc=65536

    After more reading of the man page, I have been able to compile and install the module with the following command :

    apxs -i -A -n fastcgi -o mod_fastcgi.la -c *.c

    Hope it will be useful for others…

    frntn

  • Patrick Taylor
    2:16 on May 31st, 2012

    I am trying to do a LAMP projects that specifically include social networking integration, forums, forms, picture, music, video uploads/downloads, video chat, communities of users, management tools, calendars, mailing lists and all sorts of useful applications. I understand that most of the source codes for many of the open source projects on the web that are built using LAMP stacks are mostly free; but in light of your Perfect LAMP Stack, can you tell me what is the cost of putting something like this together, and is this an area in which you operate. I look forward to hearing from you. Thanks!

  • Deepesh
    10:02 on May 31st, 2012

    The cost of putting a LAMP stack depends totally on the requirement you have.
    It can start with shared hosting which a lots of hosting company provides for small to mid size applications where you have web panels like cpanel/whm to administrate. Things are preinstalled and you cannot customize them. Cost starts from $5 a month .
    Same goes with having a Virtual Private Server (VPS) wherein you have luxury to install your own stuff, customize and shell access which is not in shared hosting. Cost starts from $20 a month.
    For large size applications you can have either managed/unmanaged dedicated server or colocated servers. They are generally expensive around $100+ a month.
    Other than these you have Amazon AWS like cloud services which costs you usage based. You can even put a LAMP stack over that.

    For your latter question, yes this is also one of the area where I operate. Feel free to ask any questions you may have.

    Thanks,

  • Michael
    5:54 on July 1st, 2012

    Has anyone gotten this to work – with the “FastCGIExternalServer” – pointed to a non – local – host?

    i.e. can this method really be used to completely separate Apache and PHP ?

    Example:
    10.0.0.2 = Apache server only. (physical box#1)
    10.0.0.3 = php-fpm server (physical box#2)

    ? I’ve tried – and I see the request come into the php-fpm access logs ( after I turned them on ). But they show remote server requests like this:

    10.0.0.2 – 30/Jun/2012:17:13:37 -0700 “GET /phpinfo.php” 404 – 2.472 768 0.00%

    whereas if I run Apache on the same machine as php-fpm the access log looks like this. ( and it works )

    10.0.0.3 – 30/Jun/2012:17:05:15 -0700 “GET /phpinfo.php” 200 /(full path on host to htdoc root)/(name of virtual host)/phpinfo.php 23.373 768 85.57%

    -Michael

  • Michael
    5:57 on July 1st, 2012

    (Resend forgot to enable cookies here)

    Has anyone gotten this to work – with the “FastCGIExternalServer” – pointed to a non – local – host?

    i.e. can this method really be used to completely separate Apache and PHP ?

    Example:
    10.0.0.2 = Apache server only. (physical box#1)
    10.0.0.3 = php-fpm server (physical box#2)

    ? I’ve tried – and I see the request come into the php-fpm access logs ( after I turned them on ). But they show remote server requests like this:

    10.0.0.2 – 30/Jun/2012:17:13:37 -0700 “GET /phpinfo.php” 404 – 2.472 768 0.00%

    whereas if I run Apache on the same machine as php-fpm the access log looks like this. ( and it works )

    10.0.0.3 – 30/Jun/2012:17:05:15 -0700 “GET /phpinfo.php” 200 /(full path on host to htdoc root)/(name of virtual host)/phpinfo.php 23.373 768 85.57%

    -Michael

  • am
    21:40 on August 15th, 2012

    /usr/local/apache2/fcgi-bin/php-cgi is a file which should exist?
    Also /fcgi-bin/php-cgi?

    i do not have these 2 files in my system.
    thanks.

  • Stephen Pritchard
    18:04 on November 30th, 2012

    Notice to author and WARNING to others.
    This article is inaccurate and miss leading. If you are going to use it, double check configuration settings yourself and RTFM.
    http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiExternalServer
    In brief php-fpm is a external IP/port service (eg. an external service to Apache accessed via an IP address) so you use the “FastCGIExternalServer” directive to send PHP requests to it. What requests are considered CGI scripts is controlled by the “filename” part of the FastCGIExternalServer directive. This should not be the CGI binary as incorrectly explained by the author above. If the above example works, it’s due to a side effect and not because it has been correctly configured.
    From the people who wrote the fastcgi module.
    “The FastCgiExternalServer directive defines filename as an external FastCGI application (Edit. eg anything matching filename is sent to the FastCGI application). If filename does not begin with a slash (/) then it is assumed to be relative to the ServerRoot. The filename does not have to exist in the local filesystem. URIs that Apache resolves to this filename will be handled by this external FastCGI application.”
    I hope this helps others reading this article and encourages the author to correct what is otherwise and interesting article.
    Thanks

  • Leave a Reply

    * Required
    ** Your Email is never shared