Apache+suEXEC+FastCGI+PHP-FPM+APC - Part 2

Click here: PART 1, if you’ve came to this directly from a Google search or you need to compile the FastASS-CGI combo.

Alright, you should have a working FastASS-CGI Configuration!  Yes, I’ve dubbed it FastASS-CGI (Fast, Apache, suexec, suhosin, Fastcgi+PHP-FPM and APC)  Those last three all go to gether which is why I just dubbed it CGI at the end.  If you have a problem with it, well… fsck you.  :P  Hahahaha, joking aside lets get into the deep and dirty portion of this configuration.

This whole part looks relatively easy but took me the longest of all to figure out.  I plan on explaining how exactly everything works in detail, so for those that already know or those just looking for the answer, sorry you’re going to have to push through this and deal with it.

Lets recap and make sure we didn’t miss anything:

  • Recompiled apache for suexec
  • Recompiled PHP and patched it for suhosin and php-fpm
  • Compiled FastCGI
  • Compiled APC
  • Made slight conf changes where needed to include all those items
  • Started Apache and PHP-FPM daemon
  • Checked logs for errors

Alright, so you probably tried to start the PHP-FPM daemon, and it threw out an error about needing some user/group information.  Since we’re using suexec, we want the owner and group option to be whatever user/group is utilizing this.  So for example you’ve created a user and group the same name as your website IE: learnix, that’s what those values would contain.  Here’s a portion of my configuration:

<value name="listen_options">
 
 Set listen(2) backlog
 <value name="backlog">-1</value>
 
 Set permissions for unix socket, if one used.
 In Linux read/write permissions must be set in order to allow connections from web server.
 Many BSD-derrived systems allow connections regardless of permissions.
 <value name="owner">learnix</value>
 <value name="group">learnix</value>
 <value name="mode">0666</value>
 </value>

And then just below that, you would do the same:

Unix user of processes
 <value name="user">learnix</value>
 
 Unix group of processes
 <value name="group">learnix</value>

So the first bit is setting the permisions if a socket is used.  In my example, I don’t use one so they are not nessessary.  However, I do recommend setting them in any case because it doesn’t hurt anything to plan for the future if you choose to use a socket over an ip connection.  The second part sets the user for who will be running the php-cgi process, which is very important.  This should be your user and not apache, www-data, nobody etc. etc.(all depending on your distro) if you are using userdir mode.

Configuring your virtual host is easy, but was a bit complicated for me to figure out.  After I had figured it out, I went back to the fastcgi documentation and re-read it.  I was misunderstanding it the whole time and I hope to provide a better explanation here.
What we only want our php scripts/files to be handled by the php-cgi process.  Everything else needs to be handled by apache.  So we must first make a new directory at the same level that our root directory, public_html, lives.  In this example i created virtual_html.  Inside of that directory we want to symlink our root, public_html, so that’s basically like our webroot with a symlink.

mkdir -p ~/virtual_html
cd ~/virtual_html
ln -s ~/public_html

From here, we just need to modify our virtual host configuration to use everything we’ve done.  In my example below you will see some commented sections for a fastcgi wrapper script.  I left those there in case anyone needed examples of those as well.  Plus I always find it handy to be able to reference something I once did in case I need to use it in the future.

ServerName learnix.net
ServerAlias www.learnix.net
DocumentRoot /home/learnix/public_html
SuexecUserGroup learnix learnix
DirectoryIndex index.html index.htm index.php index.php4 index.php5
Options +ExecCGI +FollowSymLInks +SymLinksIfOwnerMatch
 
# This is the wrapper script section.
#ScriptAlias /fcgi-bin "/home/learnix/public_html/cgi-bin/php-fastcgi.fcgi"
#AddHandler php-fastcgi .php
#Action php-fastcgi /fcgi-bin
 
# This is to forward all PHP to php-fpm.  Only this or script alias should be active
# at any time, not both
FastCgiExternalServer /home/learnix/virtual_html/public_html -host 127.0.0.1:9000 -user learnix -group learnix
AddHandler php-fastcgi .php
Action php-fastcgi /virtualhtml
Alias /virtualhtml /home/learnix/virtual_html/public_html/
 
# You must make a virtual directory so that you don't send everything web
# related to php-cgi.  This is only if you are using FastCgiExternalServer
 
Options +ExecCGI +FollowSymLInks +SymLinksIfOwnerMatch
AllowOverride all
Order allow,deny
Allow from all
 
Options +ExecCGI +FollowSymLInks +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
AllowOverride all

FastCGIExternalServer.

First is the path of our “virtual” web root.   We want this to be the full path.  I am using the ipaddress/port scheme.  You can also use the socket method which is supposed to be faster but I’m not covering that in this how to.  You will need to change the user and group to whatever you andered in your php-fpm.conf.

AddHandler

First part of this can be anything you want as far as i know and understand.  Naming it something that has some meaning to what you are doing and how you are going to use that handle makes the post sense.  Next is the extension of files that this handler will take responsibility for.

Action

This is where we define how the handler will be treated.  In this case we are saying that all .php files are only going to come from /virtualhtml which is an alias to our “virtual_html” directory.

Now you have to treat that directory like you would your public_html directory.  So we create a directive for it an specify our options.  The most important part is the Symlink options.  Without them, this whole thing wont work.

Okay, this should be it.  Restart php-fpm and apache.  Check your logs and try and view you website.  Hopefully all went well and not only is your website viewable, it’s much faster at loading.  Lets rerun that apache benchmark we did in Part 1 and compare the difference.  Change “www.somevhost.com” to your websites domain name.

ab -n 50 -c 3 -k  http://www.somevhost.com/

Hopefully there is a difference. There was for me.

This concludes the two part FastASS-CGI How-To.

Reblog this post [with Zemanta]
http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/digg_48.png http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/reddit_48.png http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/delicious_48.png http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/technorati_48.png http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/google_48.png http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/yahoobuzz_48.png http://learnix.net/wordpress/wp-content/plugins/sociofluid/images/twitter_48.png

10 comments to Apache + suEXEC + Suhosin + FastCGI + PHP-FPM + APC – Part 2

  • dmatrix7

    I have been testing a similar setup. Do you really need suexec in this configuration? If you set the user in the php-fpm.conf then php scripts execute as that user. As well you can easily add chroot to this setup to make it even more secure.

  • dmatrix7

    As well I did not need to specify the DirectoryIndex or any of the Options sections when using php-fpm. Still working on how to get phpmyadmin setup with php-fpm.

  • jackieku

    Could you explain the meaning -user & -group options of FastCgiExternalServer? I’ve read manual of mod_fastcgi, but I still have no idea about it.


    -user username|#uid (none)
    Unix (only): When FastCgiWrapper is in use, the user is used to invoke the wrapper. The -user option must be used together with -group.

    However, FastCgiExternalServer is used to configure an *external* fastcgi application (it’s php-fpm here), which is not spawned by mod_fastcgi. mod_fastcgi only connect to the socket which php-fpm is listening, am I wrong?

    So why the two options do matter?

    • @jackieku: Sure, I will give it my best. Been a while since i got this up and going and it’s been pretty solid since. The point of the external server directive is to create a process for the user needing the “root” or “admin” level permissions to run php code that would require it. So the normal php for apache runs one process for everyone but restricts what you can run unless you add other ways not mentioned in this how to to run certain things. Since i run my webserver as a userdir configuration, I host a few different websites of my own, I can decide how much “power” each one needs using this method.

      So, running this wrapper as the user, allows me the ability to then configure the php-fpm options for that wrapper on the port i chose to run 1, 2, 3 or more instances or php in creasing its “speed” in delivering the content. If you aren’t running userdir, you would still want to specify your user/group because you want this wrapper process to run as that user so that user has admin rights, essentially, to run what it would like. I can’t remember what it was but something in wordpress needed me to have certain rights to run something… I can’t remember what it was but i was running suPHP for the longest time. It worked, and it was easy…. but SLOW!!!! When i finally got this up and running….. WOW, my website loads hella fast.

      I hope that helps, if not just tell me where i may have lost ya.

  • Have you encountered issues with incorrect PHP env path variables? checking phpinfo() I get the following which appear to be incorrect (would ultimately cause problems in scripts):

    this path uses the symlink
    _SERVER["SCRIPT_FILENAME"] /var/www/farinspace/public/phpinfo.php

    these paths use the alias
    _SERVER["REQUEST_URI"] /virtualhtml/phpinfo.php
    _SERVER["SCRIPT_NAME"] /virtualhtml/phpinfo.php
    _SERVER["PHP_SELF"] /virtualhtml/phpinfo.php

    this is the correct path
    _SERVER["DOCUMENT_ROOT"] /var/www/farinspace/html

    My setup is as follows:

    FastCGIExternalServer /var/www/farinspace/public -socket /etc/php5/fpm/php5-fpm.sock -pass-header Authorization
    AddHandler php-fastcgi .php
    Action php-fastcgi /virtualhtml
    Alias /virtualhtml /var/www/farinspace/public

    Can you direct me to the documentation about the need of a “/virtualhtml” directory? I am still unclear about this part (even though it does the trick an makes it work).

    Thanks again for your write-up, it was the one the got my whole setup working.

  • Thank you very much for your how-to, I’ve found the following: http://personal.x-istence.com/post/2010/11/15/apache-modfastcgi-and-php-php-fpm … which fixes the path issues i’ve been having and gets me a step closer to understanding it all …

    any additional insights that you may have are still very much welcomed …

    • @Dimas The reason why it doesn’t work is for the fact that it’s looking for an actual cgi script directory. We trick it in to believing that virtualhtml is one with the alias, other wise it already knows through our apache config that it’s our public_html. at that point, it handles our php like we want and goes about it’s business at ludicrous speed! from what i remember it was really meant to have some php/cgi script in a dir that handles all the dirty work, well i took care of that through the apache config.

      Does that help?

  • Simon Dard

    Does anybody know how to get the status page working in Apache using the default URL of /status? Googling learned me that in Lighttpd you neeed to add the CGI-handler to that location and I’m guessing that it goes the same for Apache. I’m not familiar enough with FastCGI though, so I could not get it to work.

    At the moment I’m using a workaround: add an empty status.php to your document tree and set the relative location as the status-path in the fpm config. It works, but I’m trying to learn more about FastCGI and would like to know a proper way to do this.

    You will have to upgrade PHP to 5.3.4 or higher to get the status to work in Apache though, as 5.3.3 sends malformed headers.

    • @Simon Dard: I’m not sure, as I’ve never messed around with wanting a apache status url. I figure that if I had one, others would be able to view and the hassle of trying to make it not that way isn’t worth my time.

      Using the CLI to check the status is easier, IMO. You could even setup an event that would email you the status if you were so inclined. Personally, I use webmin to do things like this, along with virtualmin. It has some nice GUI features, showing off your stats and stuff. I would recommend checking it out.

  • Hello.

    My Ubuntu VDS based on Apache 2.2.14 (mpm-worker) + FastCGI (mod_fcgid) + PHP 5.3.2

    I setting up this config by manual: http://phphints.wordpress.com/2009/01/10/improving-php-performance-with-apache2-mpm-worker-mod_fcgid-2/

    Finally, all work.

    After this I installed APC 3.1.9 from pecl, enabled to php.ini and restart Apache.

    Atahualpa 3.6.4 stopped work correctly. My blog (images gallery, where I use Nextgen Gallery) does not show posts with galleries. Default wordpress theme works correctly.

Leave a Reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Note: Commenter is allowed to use '@User Name:' to automatically notify your reply to other commenter. e.g, if ABC is one of commenter of this post, then write '@ABC '(exclude ') will automatically send your comment to ABC. Using '@all ' to notify all previous commenters. Be sure that the value of User should exactly match with commenter's name (case sensitive).