[HOW-TO] DirectAdmin with mod_fcgid

All steps below should be done with a new clean install of DirectAdmin. It is possible to make it work on the server that already have users on it. I did that and it works perfectly fine. However, the steps will be a bit different and it won't work if you just follow instruction below.

1. Copy and paste below command into your SSH

cd /usr/local/src
wget http://mirrors.issp.co.th/apache/httpd/mod_fcgid/mod_fcgid-2.3.5.tar.bz2
tar jxf mod_fcgid-2.3.5.tar.bz2
cd mod_fcgid-2.3.5
APXS=/usr/sbin/apxs ./configure.apxs && make && make install
chmod 755 -R /var/lib/httpd
mkdir /fcgi

2. modify option file and recompile PHP.

cd /usr/local/directadmin/custombuild/
nano -w options.conf

Modify php5_cgi=yes. All else about PHP is set to no. Then, recompile PHP.

./build php n

3. Modify Apache to load mod_fcgid

3.1 Modify httpd-info.conf as below :

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

Add below text into the file httpd-info.conf

LoadModule fcgid_module /usr/lib/apache/mod_fcgid.so
 
SharememPath /var/run/fcgid_shm
SocketPath /var/lib/httpd/fcgid/sock
 
<IfModule mod_fcgid.c>
  FcgidIdleTimeout 3600
  FcgidProcessLifeTime 7200
  FcgidMaxProcesses 128
  FcgidMaxProcessesPerClass 4
  FcgidConnectTimeout 60
  FcgidIOTimeout 90
  FcgidInitialEnv RAILS_ENV production
#  FcgidInitialEnv PHP_FCGI_CHILDREN 4
#  MaxRequestsPerProcess 500
</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>

3.2 Goes into "/usr/local/directadmin/data/templates". Create custom folder. Modify virtual_host2*.conf ( 4 Files : virtual_host2.conf / virtual_host2_secure.conf / virtual_host2_secure_sub.conf / virtual_host2_sub.conf )

cd /usr/local/directadmin/data/templates
mkdir custom
cp virtual_host2*.conf custom
cd custom

Comment out each virtual_host2* files about PHP as below :

|*if CLI="1"|
#               php_admin_flag engine |PHP|
#               <IfModule !mod_php6.c>
#                       php_admin_flag safe_mode |SAFE_MODE|
#               </IfModule>
#               php_admin_value sendmail_path '/usr/sbin/sendmail -t -i -f |USER|@|DOMAIN|'
|*endif|
|*if OPEN_BASEDIR="ON"|
#               php_admin_value open_basedir |OPEN_BASEDIR_PATH|
|*endif|
|*if SUPHP="1"|
#                suPHP_Engine |PHP|
#               suPHP_UserGroup |USER| |GROUP|
|*endif|

Then, insert below text into above of the text in previous steps:

	<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/|USER|/public_html/fcgid.sh" .php
		Options +ExecCGI
		allow from all
	</Files>
	</IfModule>

4. Create fcgid.sh script

cd /usr/local/directadmin/scripts/custom/
nano -w fcgid.sh

Paste below text into fcgid.sh and then, save it.

#!/bin/sh
export PHP_FCGI_MAX_REQUESTS=0
exec /usr/local/php5/bin/php-cgi

Also create file "domain_create_post.sh" in the same folder and copy text below into the file

#!/bin/sh
 
mkdir -p /fcgi/${username}/public_html
cp /usr/local/directadmin/scripts/custom/fcgid.sh /fcgi/${username}/public_html/fcgid.sh && chmod 0700 /fcgi/${username}/public_html/fcgid.sh
cp /usr/local/directadmin/scripts/custom/php.ini /fcgi/${username}/public_html/php.ini
perl -pi -w -e "s/PHPCFG_BASEDIR/\/home\/${username}\//g;" /fcgi/${username}/public_html/php.ini
chown -R ${username}:${username} /fcgi/${username}
echo "`date`  ${domain} created  " >> /var/log/directadmin/domain_create.log

5. Copy php.ini files to " /usr/local/directadmin/scripts/custom/ "

Edit " /usr/local/directadmin/scripts/custom/php.ini " that we just copied. Search for " open_basedir " that is normally comment out. Just uncomment it and have that line like below :

open_basedir = PHPCFG_BASEDIR:/tmp:/var/tmp

6. Run command below :

chmod a+x /usr/local/directadmin/scripts/custom/*.sh

Note 1 : I have tried mod_fcgid 2.3.6 which is the latest version as of today but I ran into the problem that mod_fcgid doesn't obey " FcgidMaxProcessesPerClass" variable. If you set it to 4, PHP processes for each user should not run more than 4. It works fine with mod_fcgid 2.3.4 / 2.3.5 but not with 2.3.6. I'm sure there is something that I need to set to make it work but I have no idea what is it. So, I have to stick with mod_fcid 2.3.5 for now.
Note 2 : When there is an update for Apache / PHP, you don't have to worry if it will break your sites. You can run " ./build update_versions " without any problem.

Tested with below software :
1. CentOS 5.4 / 5.5 / 5.8 - 64 bits
2. DirectAdmin 1.362 / 1.411 - With Custombuild 1.2
3. Apache 2.2.17 / 2.4.2 - Worker MPM
4. PHP 5.2.15 - 5.2.17 / 5.3.14
5. mod_fcgid 2.3.4 / 2.3.5 / 2.3.7

Source : http://www.icez.net/blog/389/directadmin-mod_fcgid-php-fastcgi
 
 
UPDATE (2012.04.11)
About mod_fcgid 2.3.6 that doesn't obey " FcgidMaxProcessesPerClass" variable according to note above. Przemek kindly let me know in the comment that I have to edit fcgid_spawn_ctl.c ( /modules/fcgid/fcgid_spawn_ctl.c ) and change line 178:
&& current_node->vhost_id == sconf->vhost_id
to
&& current_node->vhost_id == command->vhost_id
Then, compile as usual. This seems to work as it should be now. UPDATE (2012.04.25)
When use mod_fcgid 2.3.6, you may need to add FcgidMaxRequestLen variable into /etc/httpd/conf/extra/httpd-info.conf Default before Version 2.3.6 is 1 GB, while it's only 131072 in 2.3.6. Adjust it to match your need. Also with mod_fcgid 2.3.7 released on April 23, 2012, the problem that mod_fcgid doesn't obey " FcgidMaxProcessesPerClass" variable has been fixed. You don't need to follow method in UPDATE (2012.04.11) if you use version 2.3.7.

Comments

i put in configure.apache "--with-mpm=worker" but it doesn't compile... any tips?

Create custom "configure.apache" in "/usr/local/directadmin/custombuild/custom/ap2/". So, the file path would be "/usr/local/directadmin/custombuild/custom/ap2/configure.apache"
Make sure you put all symbols correctly. Below is what I have : {syntaxhighlighter class="brush: bash;" title="configure.apache"} #!/bin/sh "./configure" \ "--prefix=/etc/httpd" \ "--exec-prefix=/etc/httpd" \ "--bindir=/usr/bin" \ "--sbindir=/usr/sbin" \ "--sysconfdir=/etc/httpd/conf" \ "--enable-so" \ "--enable-dav" \ "--enable-dav-fs" \ "--enable-dav-lock" \ "--enable-suexec" \ "--enable-deflate" \ "--enable-unique-id" \ "--with-suexec-caller=apache" \ "--with-suexec-docroot=/" \ "--with-suexec-gidmin=100" \ "--with-suexec-logfile=/var/log/httpd/suexec_log" \ "--with-suexec-uidmin=100" \ "--with-suexec-userdir=public_html" \ "--with-suexec-bin=/usr/sbin/suexec" \ "--with-included-apr" \ "--with-pcre=/usr/local" \ "--includedir=/usr/include/apache" \ "--libexecdir=/usr/lib/apache" \ "--datadir=/var/www" \ "--localstatedir=/var" \ "--enable-logio" \ "--enable-ssl" \ "--enable-rewrite" \ "--enable-proxy" \ "--enable-expires" \ "--with-ssl=/usr" \ "--with-mpm=worker" \ "--enable-headers" {/syntaxhighlighter} Check if it's running with Worker MPM by {syntaxhighlighter class="brush: bash;"} httpd -V {/syntaxhighlighter} You will see {syntaxhighlighter class="brush: bash;"} Server version: Apache/2.2.19 (Unix) Server built: Jun 6 2011 22:15:28 Server's Module Magic Number: 20051115:28 Server loaded: APR 1.4.5, APR-Util 1.3.12 Compiled using: APR 1.4.5, APR-Util 1.3.12 Architecture: 64-bit Server MPM: Worker threaded: yes (fixed thread count) forked: yes (variable process count) Server compiled with.... -D APACHE_MPM_DIR="server/mpm/worker" -D APR_HAS_SENDFILE -D APR_HAS_MMAP -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) -D APR_USE_SYSVSEM_SERIALIZE -D APR_USE_PTHREAD_SERIALIZE -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT -D APR_HAS_OTHER_CHILD -D AP_HAVE_RELIABLE_PIPED_LOGS -D DYNAMIC_MODULE_LIMIT=128 -D HTTPD_ROOT="/etc/httpd" -D SUEXEC_BIN="/usr/sbin/suexec" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="conf/mime.types" -D SERVER_CONFIG_FILE="conf/httpd.conf" {/syntaxhighlighter}

It was very easy ,Thank you!

Please help me I couldn't get it to work :( How could I get in touch with you Thanks

got the bellow error after following all of the provided instructions :( please help Service Temporarily Unavailable The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later. Additionally, a 503 Service Temporarily Unavailable error was encountered while trying to use an ErrorDocument to handle the request. Apache/2 Server at aftabdl.com Port 80

Please check log file. I'm sure the instruction above works well even with PHP 5.3. Also, make sure you do it on a new DA installation. Add new domain later after you followed instruction above. If not, you have to manually change some file by yourself.

could you please provide me with your email address so that I could be able to get it touch easier to solve the problem Thanks

Actually, it's better if you explain the problem here so that some other people may got the same situation with you will know how to fix it too. However, if you prefer it that way, please leave your e-mail here and I will contact you via e-mail. (I will delete your e-mail from here once I contact you to prevent any spammer.)

Hi there My email is ............. I will post the solution for fixing every item you helped in the comment so as you can update the post with fix too there is also one mistake in your guide chmod 755 -R /var/lib/httpd I don't know how you could be able to set it up by running this command Thanks

chmod 755 -R /var/lib/httpd is working fine. It's not a mistake at all. Also, please check your e-mail, I just e-mail you a minute ago.

After contacted with Vashi for a couple e-mails and he disappeared without any answer anymore. Look like the problem he got because he doesn't follow my instruction at all. I wrote to "chmod 755 -R /var/lib/httpd" but he chose to do it differently by using this command instead -> "chmod 755 -R /etc/httpd". So, that is his problem, not my instruction.

Quote: "Note 1 : I have tried mod_fcgid 2.3.6 which is the latest version as of today but I ran into the problem that mod_fcgid doesn't obey " FcgidMaxProcessesPerClass" variable. If you set it to 4, PHP processes for each user should not run more than 4. It works fine with mod_fcgid 2.3.4 / 2.3.5 but not with 2.3.6. I'm sure there is something that I need to set to make it work but I have no idea what is it. So, I have to stick with mod_fcid 2.3.5 for now." Yes, there is a fix. Take a look at the patch proposed here: https://issues.apache.org/bugzilla/show_bug.cgi?id=49902#c3 Edit the file fcgid_spawn_ctl.c and change line 178: && current_node->vhost_id == sconf->vhost_id to && current_node->vhost_id == command->vhost_id Przemek http://www.huan.pl

Thanks Przemek, will have to test it when I have some free time :)

I just update one server to Apache 2.4.1 and mod_fcgid 2.3.6 is required here. So, tested it and this seems to work as it should be now. Thanks a lot, Przemek.

Hello,

I've got this working for the bigger part, but the aliases like /roundcube /phpmyadmin give me "No input file specified."

Do you guys have these working with this setup?

Our servers work without that aliases problem. Tested with /roundcube /phpmyadmin /webmail

The wrong chmod was set on /var/www/, its fixed now.

Hello

1st thanks for publishing your experiences, have been very helpfull for a nono as me! I would not have been able to configure this without you!

After 6 months i ran into this small problem in my suexec log for a drupall instalation:
Security Policy Violation
"File is writable by others" - drupall/cache/normal/index.php_article=10&view=119&biscuits=chocalate.html

it turned out that drupall Boost cache outputted complex file names in its cache

And that the regular expression (\.php) matched .php in the while file name and not only on the end of the filename so i suggest changing:

Files ~ (\.php)
TO
Files ~ (\.php$)

So that the wrapper only gets invoked for files which end with .php and not files which have .php somewhere in file name string.

Files ~ (\.php$)
SetHandler fcgid-script
FCGIWrapper "/fcgi/|USER|/public_html/fcgid.sh" .php
Options +ExecCGI
allow from all
/Files

I hope this is all correct!
Thanks, good one, Joris !!!!