There are two ways to set up PHP to run via mod_fcgid
. The majority of the steps are the same for both, the only difference is in your Apache VirtualHost configuration. This document will explain both.
Step 1: Installation and Preparation
Chances are you’ve already done these steps
- Install the PHP CGI binary
- Install and enable the following modules:
mod_fcgid
mod_actions
(only required for Option 2)
- Disable
mod_php
if it is installed
Typically you’ll install these using the package manager for your OS (e.g. apt-get
or yum
).
Step 2: Create PHP launcher in a suEXEC-friendly location
suEXEC only allows scripts under /var/www/ to be executed, and is picky about permissions.
Create a directory under which we can put our script:
mkdir /var/www/fcgi-bin/
mkdir /var/www/fcgi-bin/someuser/
Next we make our script:
----- File: /var/www/fcgi-bin/someuser/php.fcgi -----
#!/bin/bash
exec /usr/bin/php-cgi
And of course mark it as executable and set ownership:
chmod a+x /var/www/fcgi-bin/someuser/php.fcgi
chown -R someuser:someuser /var/www/fcgi-bin/someuser/
It’s also a good idea to remove write permission from this dir and all its files.
chmod a-w -R /var/www/fcgi-bin/someuser
Note that any additional PHP configuration you want to do can go into that file. Specifying
a per-user php.ini file for example by changing PHPRC and other PHP environment variables.
Step 3: Apache Configuration
First of all, remove (comment out) any PHP configuration already there. Next, you may want to
add the following fcgid configuration:
AddHandler fcgid-script .fcgi .php .fpl # useful for other fastcgi
FcgidConnectTimeout 20 # 20 second timeout on connnect
FcgidMaxRequestLen 268435456 # 256MB upload/post limit
FcgidMaxProcessesPerClass 10 # Up to 10 PHP processes per user at a time
FcgidIOTimeout 300 # 5 minute timeout on request
For the actual PHP configuration, there are two ways to do it. The first way requires ExecCGI to be set on your document root directory, and the second does some munging with URL paths that might break RewriteRules. Note that the configuration shown below is the bare minimum to get this working. You may also want to add thinks like setting a default content-type, additional
configurability, etc.
Option 1: Using FcgidWrapper
<VirtualHost *:80>
Servername example.com
DirectoryIndex index.php
SuexecUserGroup someuser someuser
AddHandler fcgid-script .php
FcgidWrapper /var/www/fcgi-bin/someuser/php.fcgi .php
<Directory /home/someuser/public_html/>
Options +ExecCGI
</Directory>
</VirtualHost>
Option 2: Using Action
Note that this option has some security concerns, since you’re granting direct access to your executable PHP invocatation script. It also uses /php-fcgi/php.fcgi
as your script name, which could make for problems down the road.
I’m including this example in the interest of completeness, but Option 1 is probably better all around.
<VirtualHost *:80>
Servername example.com
DirectoryIndex index.php
SuexecUserGroup someuser someuser
ScriptAlias /php-fcgi/ /var/www/fcgi-bin/someuser/
AddHandler php-via-fcgi .php
Action php-via-fcgi /php-fcgi/php.fcgi
</VirtualHost>
With this setup, ExecCGI
needs to be set for the directory where you find php.fcgi
instead of where your .php
files are located. We handle this implicitly by using ScriptAlias
instead of Alias
.
Additional Notes
-
The suEXEC security checks are applied to the
.fcgi
file, not to the.php
files. This means that the scripts themselves and the directories they reside in may be owned by any user (for better or for worse). -
If you have multiple users, then each user gets his own directory and
php.fcgi
file under/var/www/fcgi-bin/
. You can customize the PHP environment for each user by customizing that file. -
If you aren’t using suEXEC, then you don’t need a per-user
php.fcgi
file, nor does it need to be in a per-user directory. Simply creating one file at/var/www/php-fcgi/php.fcgi
will be sufficient. -
Your working directory while executing your PHP scripts will be
/var/www/php-fcgi/someuser/
. Make sure you eitherchdir
to your desired working directory or design your scripts so that they won’t depend on this particular detail.