Securing Apache 2.2 with suEXEC and fcgid

Ever thought about switching from native Apache Httpd 2.2 module for php5 to fastcgi (or fcgid as a fastcgi alternative)?

Here you can find some data on that fcgid is faster, a good alternative to php5_module/libphp5.

So, here’s a quick info on how I set it up.

First of all, what’s suEXEC?

suEXEC allows you to run php scripts as a specific user. This is useful when you’re creating ftp accounts for ppl, hopefully disallow them bash/shell access, and of course want to set permissions so the ftp user may still edit all his files but keep permissions for other users to a minimum. As Apache Httpd runs as a different user by default, www-data, you have a problem, and may have to set permissions up to 777, read+write for all.

Then someone with shell access and knowing the path to the web space may change files.

With suEXEC you won’t have to add permissions. Those for the owner (ftp user) are enough.

suExec requires PHP to run as fastcgi. But as that one will also save some resources and hopefully speed up your site, well, that’s good as well, right?

Setup is complexer than php5-module though.

Install libapache2-mod-fcgid and php5-cgi, then enable fcgid (apache module, so from /etc/apache2/modules-available/ to /etc/apache2/modules-enabled/).

/etc/apache2/mods-enabled/fcgid.conf:

AddHandler fcgid-script .fcgi .php

IPCConnectTimeout 20

/etc/apache2/conf.d/php-fcgid.conf:

# Where to look for the php.ini file?

#  DefaultInitEnv PHPRC        “/etc/php5/cgi”

# Maximum requests a process handles before it is terminated

MaxRequestsPerProcess       1000

# Maximum number of PHP processes

MaxProcessCount             5

# Number of seconds of idle time before a process is terminated

IPCCommTimeout              240

IdleTimeout                 240

#FCGIWrapper /usr/bin/php-cgi .php

FCGIWrapper /var/www/cgi-bin/php-cgi .php

ServerLimit           512

StartServers            3

#  MinSpareThreads         3

#  MaxSpareThreads        10

#  ThreadsPerChild        10

MaxClients            300

MaxRequestsPerChild  1000

The last 3 commented out settings were not accepted for me, but were in the article linked above. You may want to check them, they may have been in fcgid in older or newer versions or sth.

suEXEC requires the files to be under /var/www by compiled code-setting. So unless you compile it yourself, you’ll have to have your webspaces and ftp users under that folder.

/usr/bin/php-cgi is your FCGIWrapper, php files being passed to it. suEXEC requires it to be executed as the same user as well though, resulting in it having to be under /var/www.

Thus you may do a folder structure like this:

/var/www/web1/cgi-bin/php-cgi

/var/www/web1/htdocs

/var/www/web2/cgi-bin/php-cgi

/var/www/web2/htdocs

Where web1/2 would be the ftp accounts, the htdocs folder your virtual-host target, and php-cgi being owned by the user web1/2 and executable for him.

Also make sure the folders and files in a users dir are only writeable for that user.

Now on to the virtual hosts:

<VirtualHost *:80>

Options +ExecCGI

AllowOverride All

SuexecUserGroup web1 ftponly

FCGIWrapper /var/www/web1/cgi-bin/php-cgi .php

You’ll have to add Options +ExecCGI for the cgi to be executed if you don’t have it already, eg by default/global config.

With SuexecUserGroup you will then set the user and group the php files are to be executed as.

With the FCGIWrapper line you set the cgi script to be used for .php files.

In the end, may sure your /etc/php5/cgi/php.ini file is to your wishes.

An alternative to the Wrapper script is the action module.

As that one caused even more trouble and settings I didn’t continue trying it out. See here for example, note however you should not use that folder like that. Make your own with only the script you need inside it, as seen above.