I’m a software developer who runs Scribophile, an online writing group for serious writers, Writerfolio, an online writing portfolio service for freelancers, and Standard Ebooks, a publisher of beautifully-illustrated public-domain ebooks.

Installing Apache + mod_fastcgi + PHP-FPM on Ubuntu Server Maverick

Recently I was looking to speed up one of my Apache + mod_php installs. The problem with Apache + mod_php is that Apache must spawn and then destroy a new instance of PHP whenever a script is called. This leads to performance degradation and eventually process bloat as the Apache process expands in memory to astronomical sizes.

Lots of options with similar names

There are lots of alternatives to speed up Apache + PHP, but unfortunately they all have similar-sounding names and can be combined in a few permutations. It can be confusing deciding which alternative to pick, and even more confusing figuring out how to set it up. I want to quickly describe some of the main alternatives to help clear things up before we start (but for those of you with short attention spans, the best one appears to be Apache + mod_fastcgi + PHP-FPM).

  1. Apache + mod_fastcgi: FastCGI is a module that allows you to neatly solve mod_php’s big problem, namely that it must spin up and destroy a PHP instance with every request. FastCGI instead keeps an instance of PHP running in the background. When Apache receives a request it forwards it to FastCGI, which feeds it to its already running instance of PHP and sends the result back to Apache. Apache then serves the result.

    Without the constant build-and-destroy of new PHP processes, FastCGI is a great memory saver and performance booster. My Apache + mod_php install, which would constantly bloat to 1000′s of MB in memory usage and invoke OOM-Killer without mercy, has been humming along at a steady ~200MB for the past few months without a single problem after switching to mod_fastcgi.

  2. Apache + mod_fcgid: Why, oh why, did someone build an alternative to FastCGI only to call it by the almost-identical name of fcgid? From what I understand, fgcid is a binary-compatible alternative to FastCGI–that is, it does more or less the same thing, but in a different way. It seems that some people prefer mod_fcgid over mod_fastcgi because of better stability and maybe even slightly better performance. But for the kind of traffic I’m getting, there wasn’t any difference.
  3. Apache + mod_fastcgi + PHP-FPM: PHP-FPM (A.K.A. PHP5-FPM) is a process manager for PHP. Confusingly, it was only recently bundled with PHP, so you might find some tutorials telling you to download the source and others to just use apt-get. I believe that if you’re using PHP >= 5.3, which you would be if you installed it in Maverick with apt-get, that you don’t need to download the source to get it working. I’ll talk more about this later.

    From what I understand, PHP-FPM is like FastCGI, but with additional PHP-specific optimizations built in. Since it’s specially built for PHP, it should give you the best performance, and so is the best of these three alternatives. It’s the one we’ll be focusing on for this post.

Getting it installed

For some reason it seems that there’s a glut of tutorials for setting up Nginx + PHP-FPM, but almost none for Apache + PHP-FPM. While Nginx is great, Apache has worked well for me for many years and I’m a “if it ain’t broke, don’t fix it” kind of guy.

Thankfully, it turns out that despite the severe lack of simple online tutorials it’s not so hard to set up Apache + mod_fastcgi + PHP-FPM on Ubuntu Server. Here we go!

  1. Enable the Multiverse repository, which is where libapache2-mod-fastcgi lives. For some reason it’s not included in Ubuntu Server, so we have to append it to our /etc/apt/sources.list:

    echo -e "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs) main restricted multiverse\ndeb-src http://archive.ubuntu.com/ubuntu $(lsb_release -cs) main restricted multiverse" | sudo tee -a /etc/apt/sources.list > /dev/null
  2. Install Apache and other required software. You must use the Apache Worker variant, not the Apache Prefork variant. The difference between the two is important, but you can look that up somewhere else.

    sudo apt-get install apache2-mpm-worker libapache2-mod-fastcgi php5-fpm
  3. When you start the PHP5-FPM service on a default install, you’ll get a warning about a setting called “pm.start_servers” not being initialized. This won’t affect your install, but it can get annoying. To stop this message from showing up when starting or stopping the PHP5-FPM service, run:

    sudo sed -i 's/;pm.start_servers/pm.start_servers/g' /etc/php5/fpm/pool.d/www.conf
  4. Enable some Apache modules that we’ll be using:

    sudo a2enmod actions fastcgi alias
  5. And now for the secret sauce: Setting up your Apache virtual host so that it shuffles PHP requests to PHP-FPM/FastCGI. For this example I’ll use Apache’s default site, but you’ll probably want to use your own. Edit /etc/apache2/sites-available/default using Nano (or your favorite editor):

    sudo nano /etc/apache2/sites-available/default

    Paste the following somewhere in your VirtualHost block using ctrl + shift + v:

    FastCgiExternalServer /var/www/php5.external -host 127.0.0.1:9000
    AddHandler php5-fcgi .php
    Action php5-fcgi /usr/lib/cgi-bin/php5.external
    Alias /usr/lib/cgi-bin/	/var/www/

    Remember that when using your own VirtualHost, you’ll probably be changing the default web root from /var/www/ to a different directory.

    Also note that the “file” php5.external doesn’t have to exist—it’s just a socket.

  6. Restart both Apache and the PHP-FPM services:

    sudo service apache2 restart && sudo service php5-fpm restart

And that should do it!

Testing your install

To test this default install, create a new PHP file in Apache’s default document root and access it from your web browser.

  1. Create the PHP file:

    echo "<?php phpinfo(); ?>" | sudo tee /var/www/test.php > /dev/null && sudo chgrp www-data /var/www/test.php
  2. Test it in your browser! Visit http://localhost/test.php and check the output:

And that should be about it. Enjoy your new speedy Apache install!

By the way, I’m more of a developer than a sysadmin, so if any experienced sysadmins want to chime in on this setup then by all means please do so.

References

Comments

  1. Stan Tkhorovsky

    Very good post. Thank you

  2. anggiaj

    Thank you very, i done my mint installation because your articles

  3. Adam Cooper

    The 500 errors are quite likely caused by a bug in mod_fastcgi. It’s been reported https://bugs.launchpad.net/ubuntu/+source/libapache-mod-fastcgi/+bug/743633 but it may be a while before a solution is made available. Especially as it has likely been fixed in the Natty (11.10)

  4. Christer Klingstedt

    Thank you ! Cut waiting times by 90% on my server. I would like to enable my firewall but I can’t find the proper port(s) to open (opening p. 9000 for TCP+/-UDP does not help).

  5. Luc Step

    Hello,
    I tried your configuration on Natty, but it complains on not finding the file ‘/usr/lib/cgi-bin/php5.external/index.php

    What am I supposed to put in that “Action php5-fcgi” ? my root dir and php files are located in /var/www/mediawiki, but you wrote about this just for the Alias directive…

  6. Alex Cabal

    I’m not sure without seeing your specific configuration.

    The Alias directive is there so that Apache knows that files in your web root (in this example /var/www/) should get executed by PHP.

    Have you made sure to change /var/www/ in the example to your own web root?

    If you can’t use mod_alias, then I’m unfortunately not experienced enough to be able to recommend an alternative.

  7. MacIntox

    Hello Alex.
    You should maybe consider this:

    http://voidweb.com/2010/10/get-high-performance-php-fpm-socket-connections/

  8. Tim

    I was getting internal server errors as well. Question though, what config are you using to pass requests on part # 5 if using mod_fcgid instead? FastCgiExternalServer isn’t recognized and spits out an error if I try to flip it over to fcgid.

  9. Alex Cabal

    PHP-FPM and FCGID are totally different and their configurations aren’t compatible. For my servers running FCGID, I add the following to my Apache Virtualhost directive:

    #for mod_fcgid
    AddHandler fcgid-script .php
    FCGIWrapper /usr/lib/cgi-bin/php5 .php
    ProcessLifeTime 7200
    IPCCommTimeout 7200
    IPCConnectTimeout 300

    These may also be duplicated in the FCGID conf file but I can’t look right this second.

  10. Tim

    Ok cool…thanks! I’ve only used suphp in the past with apache and then php-fpm with nginx, so still trying to get my head around using fastcgi on apache for the first time.

    Makes sense now on php-fpm and fcgid if they aren’t compatible. I was banging my head against a wall trying to get them to play together.

  11. Is it possible to run MySQL (and other libraries) in Apache2 + php5-fpm?

    [...] I followed a guide on http://alexcabal.com/installing-apache-mod_fastcgi-php-fpm-on-ubuntu-server-maverick/ [...]

  12. Jared Fine

    To answer your question “Why, oh why, did someone build an alternative to FastCGI only to call it by the almost-identical name of fcgid?”.

    mod_fcgid was introduced to be binary compatible with mod_fastcgi, but with better control over spawning processes. Also mod_fastcgi is non-free so most repositories only include mod_fcgid.

    Cheers.

  13. CB

    After running your steps my server memory when from 50% to 137%. I’m not getting any errors but php5-fpm now shows about 20 times when I run ‘top’. I’m using apache and nginx as a reverse proxy. Any ideas?

  14. Installing apache, fastcgi & php-fpm on dragonflybsd » From the desk of

    [...] [...]

  15. Ahmed Kamal

    Hi,

    I would like to thank you on the very nice article, every think works fine with for php requests, but for other requests like (JS, CSS, Images), I got either 404 or 403.

    Is .htaccess working fine with php-fpm and FCGI as Apache supposed to handle this?

    Thanks.

  16. Josh

    Do you have a good tutorial for setting up fcgid apache and php? I followed yours for php-fpm, but I’m getting those 500s everyone is talking about and now I’d like to switch, as you said you have done.

    Thanks!

  17. Aziz

    Hey Alex. Just wanted to give you a heads up on WordPress installs and php5-fpm. The reason why you may have getting 500 error codes might be due to apache going into an infinite loop with internal redirects. If you set LogLevel debug, you can get a backtrace to the underlying problem.

    If you have your WordPress directory in a sub-directory, and followed the WordPress guidelines on copying the .htaccess and index.php file outside of the sub-directory and into your doc-root, then that’s where the problem might. I’m not entirely sure what causes this, perhaps someone with more knowledge on the subject can chime in, but I’ve managed to implement a dirty hack (on my testing server) in the root .htaccess file.

    RewriteEngine On
    RewriteBase /wordpress/
    RewriteRule ^index\.php$ – [L]
    RewriteCond %{REQUEST_URI} !^/path/to/your/php5-fpm-socket/*
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /wordpress/index.php [L]

    In your tutorial /path/to/your/php5-fpm-socket/ would be /usr/lib/cgi-bin/*

    Not sure how it fairs in the long run though. I’m still testing and reading up to see if there’s a more cleaner solution.

  18. Alex Cabal

    Thanks Aziz, however the site using the configuration in the post wasn’t a WordPress install.

  19. Aziz

    typo:
    into your doc-root, then that’s where the problem might originate from.

  20. Aziz

    Oh alright, did you try to investigate a little further? Any assumptions on what could of happened?

  21. Alex Cabal

    No; I’m not much of a sysadmin and the problem happened on a busy live site, so I just went back to what was known to work, which was Apache + FCGID.

  22. Prashant

    Its a WOW post. I searched the webs for 3 hours and got no where. With this post I got it running it under 90 seconds.

  23. whn09

    Great!

  24. Blitz.io Tests Against Apache Worker, Apache Prefork, Apache with PHP-FPM, and Nginx with PHP-FPM in a 256MB RAM VPS - VirtuallyHyper

    [...] didn’t see that much of an increase. Now there are other fast cgi modules. The blog “Installing Apache + Mod_FastCGI + PHP-FPM on Ubuntu Server Maverick” clarifies that different versions, from the blog: Apache + mod_fastcgi: FastCGI is a module [...]

  25. premiso

    I have the same random 500 errors. I plan on switching to the mod_php and hope that works. I may also decide to try nginx, but we will see.

    But it gets annoying not knowing why or how this is occuring. I have Varnish installed as well on my setup, and thought it was that for the longest time. Now I have narrowed it down to PHP / Apache. If you do come across anything please update! I will do the same :)

    Thanks!

  26. Joe

    For those with the 500 errors, the first line in this code needs to point to a unix socket, not a TCP/IP address / port – this is on Ubuntu 12.10.x – if you look inside /etc/php5/fpm/pool.d/www.conf you will find FPM is set up to listen to a unix socket.

    Hope this helps!

    FastCgiExternalServer /var/www/php5.external -socket /var/run/php5-fpm.sock
    AddHandler php5-fcgi .php
    AddHandler php5-fcgi .wfr
    Action php5-fcgi /usr/lib/cgi-bin/php5.external
    Alias /usr/lib/cgi-bin/ /var/www/

  27. nex

    Thanks a lot Joe, you pulled me straight out of despair :)

  28. Silver Moon

    You mentioned that mod php spins new php instance for every request.
    Does it do so even with apache mpm worker ?

  29. Alex Cabal

    Yes. If configured with mod_php, Apache starts a new PHP instance each time it receives a request to serve a PHP script, then destroys the instance when the script is done. With php-fpm, the FPM process keeps a certain number of PHP instances alive at all times, and Apache sends requests to those living instances instead of starting and destroying a new one with each request.

  30. Install Mod-FastCGI and PHP5-FPM on Ubuntu » Starck Lin

    […] INSTALLING APACHE + MOD_FASTCGI + PHP-FPM ON UBUNTU SERVER MAVERICK […]

  31. At last

    Joe’s configuration snippet is what made everything work for me, after two days of searching. At first I was using mod_rewrite, but php-fpm kept using the post-rewrite URL, complete with the virtual .fcgi file. Using “Alias” to a non-existant directory instead causes the PATH_TRANSLATED attribute sent by mod_fastcgi to the socket to contain the correct path to the script.

    Some posts on stackoverflow/serverfault will say that the “SCRIPT_NAME” fastcgi attribute is what counts, but PATH_TRANSLATED seems to take precedence.

Leave a Comment