[HOW-TO] DirectAdmin - Run Apache with "mod_fcgid on PHP 5.2 / 5.3" and "mod_fastcgi + PHP-FPM on PHP 5.3" on the same server

This guide [ Run Apache with "mod_fcgid on PHP 5.2 / 5.3" and "mod_fastcgi + PHP-FPM on PHP 5.3" on the same server in different Virtualhosts ] has 3 parts altogether. So, you may need to take a look at 2 other parts as well :

1. [HOW-TO] DirectAdmin with mod_fcgid
2. [HOW-TO] Enable and setup PHP-FPM in DirectAdmin (PHP 5.3)

After I've tried a few days on my servers, I found that PHP-FPM should be able to configure to make it work separately per virtualhost. So, now, since I already have mod_fcgid installed, I can also set specific virtualhost to use PHP-FPM until 'OnDemand' feature from PHP-FPM is completed. Then, PHP-FPM should be ready for shared hosting. (I choose to use PHP-FPM on highload website only. Any other website on the same server still use mod_fcgid as usual.)

1. Install mod_fastcgi Copy and paste below command into your SSH
cd /usr/local/src
wget http://www.fastcgi.com/dist/mod_fastcgi-2.4.6.tar.gz
tar zvxf mod_fastcgi-2.4.6.tar.gz
cd mod_fastcgi-2.4.6
cp Makefile.AP2 Makefile
make top_dir=/etc/httpd
make install top_dir=/etc/httpd
chmod 755 -R /var/lib/httpd
mkdir /fcgi

2. Create custom PHP compile file and recompile PHP to enable PHP-FPM. (Note that mod_fcgid installed still works while doing this PHP-FPM things. So, you don't need to worry if this compile will cause mod_fcgid to fail.)

./build php n

3. Modify Apache (httpd-info.conf) to load mod_fastcgi

nano -w /etc/httpd/conf/extra/httpd-info.conf

Add below text into the file httpd-info.conf

LoadModule fastcgi_module /usr/lib/apache/mod_fastcgi.so

So, with both mod_fcgid and mod_fastcgi, httpd_info.conf will looks like this :

.....
LoadModule fcgid_module /usr/lib/apache/mod_fcgid.so
LoadModule fastcgi_module /usr/lib/apache/mod_fastcgi.so

<IfModule mod_fcgid.c>
   SharememPath /var/run/fcgid_shm
   SocketPath /var/lib/httpd/fcgid/sock
</IfModule>

<IfModule mod_fcgid.c>
  FcgidIdleTimeout 3600
  FcgidProcessLifeTime 7200
  FcgidMaxProcesses 17
  FcgidMaxProcessesPerClass 16
  FcgidConnectTimeout 60  
  FcgidIOTimeout 90
  FcgidInitialEnv RAILS_ENV production
</IfModule>

<Directory "/home">
        AllowOverride All
        Options SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
        <IfModule sapi_apache2.c>
        php_admin_flag engine off
        </IfModule>
        <IfModule mod_php5.c>
        php_admin_flag engine off
        </IfModule>
</Directory>

4. Modify VirtualHost that you want to use PHP-FPM (Example here is "admin" user)

nano -w /usr/local/directadmin/data/users/admin/httpd.conf

Modify httpd.conf file to add below code :

<IfModule mod_fastcgi.c>
   <FilesMatch \.php$>
      SetHandler php5-fcgi
   </FilesMatch>
   <Location "/fastcgiphp">
      Order Deny,Allow
      Deny from All
      # Prevent accessing this path directly
      Allow from env=REDIRECT_STATUS
   </Location>
   Action php5-fcgi /fastcgiphp
</IfModule>

<IfModule mod_fastcgi.c>
   FastCgiExternalServer /usr/local/bin/admin -socket /fcgi/admin/public_html/admin.sock
   Alias /fastcgiphp /usr/local/bin/admin
</IfModule>

Also comment out some mod_fcgid in that virtual host to make sure it won't load at all (From what I tried, without comment them out, it will load mod_fcgid instead of PHP-FPM) The code will look like below :

.....
        SuexecUserGroup admin admin
        CustomLog /var/log/httpd/domains/testdomain.com.bytes bytes
        CustomLog /var/log/httpd/domains/testdomain.com.log combined
        ErrorLog /var/log/httpd/domains/testdomain.com.error.log

<IfModule mod_fastcgi.c>
   <FilesMatch \.php$>
      SetHandler php5-fcgi
   </FilesMatch>
   <Location "/fastcgiphp">
      Order Deny,Allow
      Deny from All
      # Prevent accessing this path directly
      Allow from env=REDIRECT_STATUS
   </Location>
   Action php5-fcgi /fastcgiphp
</IfModule>

<IfModule mod_fastcgi.c>
   FastCgiExternalServer /usr/local/bin/admin -socket /fcgi/admin/public_html/admin.sock
   Alias /fastcgiphp /usr/local/bin/admin
</IfModule>

	<Directory /home/admin/domains/testdomain.com/public_html>
                Options +Includes -Indexes
#        <IfModule mod_fcgid.c>
#               <Files ~ (\.fcgi)>
#                       SetHandler fcgid-script
#                       Options +FollowSymLinks +ExecCGI
#               </Files>
#	</IfModule>
#	<IfModule mod_fcgid.c>
#	<Files ~ (\.php)>
#               SetHandler fcgid-script                 
#               FCGIWrapper "/fcgi/admin/public_html/fcgid.sh" .php
#               Options +ExecCGI
#               allow from all
#	</Files>
#	</IfModule>
#                suPHP_Engine ON
#               suPHP_UserGroup admin admin
        </Directory>
.....

5. Done... now restart Apache and see it working.. If you check PHP status page, at "Server API", you will see "FPM/FastCGI" instead of "CGI/FastCGI". Oh... by the way, I won't show you how to install XCache. You can search on BXTra.net to see instruction how to do that.



===============================================================

Below is what Brandon wrote, Just in case you want to understand how things work

===============================================================

Globally:
<IfModule mod_fastcgi.c>

# Directory where the PHP-FPM fastcgi sockets exist
FastCgiIpcDir /usr/local/var/run/fastcgi

# All files ending in .php will be handled by php-fpm
<FilesMatch \.php$>
SetHandler php5-fcgi
</FilesMatch>

# Fake directory that handles php-fpm requests. 
# Directory can be anything, it should not exist and will not be visible to the end-user
# Each virtual host will alias this to a PHP-FPM socket
<Location "/fastcgiphp">
Order Deny,Allow
Deny from All
# Prevent accessing this path directly
Allow from env=REDIRECT_STATUS
</Location>

# Direct all PHP requests to the /fastcgiphp fake directory
# Each virtual host will alias this to a PHP-FPM socket
Action php5-fcgi /fastcgiphp
</IfModule>


Per php-fpm socket (this may be per virtual host, per user, per server, etc):
<IfModule mod_fastcgi.c>
# Reference to external PHP-FPM socket
# The path (/usr/local/bin) must exist but the filename (bob-php-fpm) does not have to exist.
# The socket file (bob-php-fpm.sock) should exist in the directory 
# specified by the FastCgiIpcDir directive (/usr/local/var/run/fastcgi)
FastCgiExternalServer /usr/local/bin/bob-php-fpm -socket bob-php-fpm.sock
</IfModule>

Per virtual host:
<VirtualHost *:80>
ServerName ...
...
<IfModule mod_fastcgi.c>
# Alias php requests to our PHP-FPM socket
Alias /fastcgiphp /usr/local/bin/bob-php-fpm
</IfModule>
</VirtualHost>

Note (That you may need to know) :

1. "The important part when config fastcgi are maxClassProcesses (from the mod_fastcgi point of view, each VirtualHost with FastCGI will use only one (master) process) and maxProcesses, which determines the total max amount of processes across your whole server (think: 50 VHosts with each one master)."

2. All configurations here (Both PHP-FPM in another tutorial and FastCGI configuration) doesn't mean it can work efficiently in real world. I just put it to make it work. Configuration needs to be done to gain better performance / stability as needed.

3. Don't forget to use Opcode Cache. After I tried PHP-FPM for a while, I noticed that the load went higher than before which is strange. But then, I checked XCache to see if it's working or not. From what I know it doesn't working at all. I used XCache-admin to monitor both per virtualhost and per machine (By IP). None of them were cached. So, I tried to install APC instead. I can now see it's working. The load went down to where it should be. That means, it's time for me to switch to APC.

4. One of the problem about PHP-FPM to work under Virtualhost is that you have to have different PHP-FPM setting per Virtualhost even it's on the same user. Let's say if you have a domain that usually can access through port 80 and the same domain can also accessed through SSL which is port 443. Then, you have to have 2 PHP-FPM settings for each of them.

5. With experienced for about a week about PHP-FPM, I just realized that you can mix many things if doing it in mod_fcgid. You can have "php-cgi" file in different PHP version like 5.2 and 5.3. Set it in the FCGIWrapper script, then, each Virtualhost can have different PHP versions / settings

6. Update (2011.02.10) Note about APC, after tested on 2 different servers. Both of them loaded APC via extension in PHP-FPM configuration file. However, Machine A with 2 Virtualhosts that have PHP-FPM enabled, each Virtualhost loaded APC extension separately. Machine B has only one Virtualhost that run PHP-FPM. Machine B doesn't have problem of APC restart very often. So, the uptime is great. Machine A was different, I usually saw Uptime went up to 3 minutes the most, then, set back to 0. So, I tried to load APC via php.ini file at PHP-FPM startup instead of under PHP-FPM configuration file. Now, it works great. The uptime is not reset again as it used to be.

7. Update (2011.02.11) Note about PHP-FPM - dynamic pm, if you know you have a pretty busy server on that Virtualhost, I suggest to set it "pm.start_servers" and "pm.min_spare_servers" to a high number to prevent it to re-spawn too often. One of my server which is pretty busy always had a high load after I switched to PHP-FPM. (APC enabled) Changed this value according to suggestion on PHP-FPM log help a lot.

Tested with below software :
1. CentOS 5.4 / 5.5 - 64 bits
2. DirectAdmin 1.37 - With Custombuild 1.2
3. Apache 2.2.17 - Worker MPM
4. PHP 5.2.17 / 5.3.5
5. PHP-FPM in PHP 5.3.5
6. mod_fcgid 2.3.5
7. mod_fastcgi 2.4.6
8. XCache 1.3.0
9. APC 3.1.7

Source :
- http://forum.nginx.org/read.php?3,119942,120390 - Thanks to Brandon for detail explanation. I can understand what I am doing once I read his instruction.
- http://blog.foaa.de/2010/11/php-apache-and-fastcgi-a-comprehensive-overview/

UPDATE (2011.10.07)
You may need to specified the correct path in Apache configuration so that you will not have this problem -> Fix the Problem with $_SERVER["SCRIPT_FILENAME"] when using Apache + PHP-FPM + mod_fastcgi

FROM :

<IfModule mod_fastcgi.c>
   FastCgiExternalServer /usr/local/bin/admin -socket /fcgi/admin/public_html/admin.sock
   Alias /fastcgiphp /usr/local/bin/admin
</IfModule>

TO :

<IfModule mod_fastcgi.c>
   FastCgiExternalServer /home/admin/domains/admin.com/public_html/index.php -socket /fcgi/admin/public_html/admin.sock
   Alias /fastcgiphp /home/admin/domains/admin.com/public_html/index.php
</IfModule>

UPDATE (2012.04.10)
Just tried to run mod_fastcgi + PHP-FPM with Apache 2.4.1. The original mod_fastcgi doesn't work correctly. Grab a new mod_fastcgi from ByteInternet here Then, extract it and apply the patch using following command :

patch -p1 < debian/patches/byte-compile-against-apache24.diff

Then, compile it per instruction above. Do not worry about the word debian. I tested it with CentOS and it works fine.

Some people may think that why I don't use mod_proxy_fcgi, a default module come with Apache 2.4.1, which should play nicely with PHP-FPM. That was what I actually want to do at first but after searching around, I found that mod_proxy_fcgi only support Network Port, not Unix socket. If I want to use it, I need to change many things to make it work. But with mod_fastcgi, all configurations I used before can still be used without any modification.

Comments

i found a great article while googling , I recommend the article to everybody http://www.discusswire.com/running-php-5-2-5-3-server/

Just as an FYI for future viewers of this post: Since Apache 2.4.9, the mod_proxy_fcgi module does, indeed, support connections to php-fpm over a Unix socket. And version 2.4.10 allows you to set up a reverse proxy and send the request through it, which I've found is the most reliable and accurate way to pass the request to php-fpm. See the Apache 2.4 documentation page for mod_proxy_fcgi at the Apache website and use the example at the bottom of the page.