HowTo: Apache2, SuExec, PHP5 and FastCGI for Virtual Domains

These notes are specific to Ubuntu 7.10 (Gutsy) and 8.04 (Hardy) but can be easily adjusted for other distributions.

Running PHP v5 on Apache v2.x requires the use of CGI and php-cgi if the recommended apache2-mpm-worker configuration is to be maintained. This prevents the use of libapache2-mod-php5 because that module requires apache2-mpm-prefork - these two mpm's are mutually exclusive.

Check what is installed; first Apache:

$ dpkg-query -l 'apache2*' | egrep '^ii'
ii  apache2                2.2.4-3build1  Next generation, scalable, extendable web server
ii  apache2-mpm-worker     2.2.4-3build1  High speed threaded model for Apache HTTPD
ii  apache2-utils          2.2.4-3build1  utility programs for webservers
ii  apache2.2-common       2.2.4-3build1  Next generation, scalable, extendable web server

And now PHP:

~$ dpkg-query -l '*php*' | egrep '^(ii|un)'
un  libapache2-mod-php4 <none>(no description available)
un  libapache2-mod-php5 <none>(no description available)
un  php-doc             <none>(no description available)
un  php-pear            <none>(no description available)
un  php3                <none>(no description available)
ii  php5-cgi            5.2.3-1ubuntu6.2 server-side, HTML-embedded scripting languag
ii  php5-common         5.2.3-1ubuntu6.2 Common files for packages built from the php
un  php5-json           <none>(no description available)
ii  php5-mysql          5.2.3-1ubuntu6.2 MySQL module for php5
un  php5-mysqli         <none>(no description available)
un  phpapi-20060613     <none>(no description available)</none></none></none></none></none></none></none></none> 

The FastCGI module:

$ dpkg-query -l '*fcgi*' | egrep '^(ii|un)'
ii  libapache2-mod-fcgid 1:2.1-2        an alternative module compat with mod_fastcgi

The ii at the beginning of each line above denotes installed. Some package have dependencies on others. Use apt-get to install the packages and their dependencies if they aren't already:

$ sudo apt-get install apache2 php5-cgi libapache2-mod-fcgid

When using the Virtualmin virtual hosting management tool the home directories of each domain are under /home/. This differs from the Apache convention of /var/www/ and causes issues with suexec refusing to execute CGI programs due to permissions problems.

Two examples of errors from /var/log/apache2/suexec.log:

uid: (1014/intuitivenipple) gid: (1013/1013) cmd: php-fcgi-wrapper
cannot stat program: (php-fcgi-wrapper)

uid: (1014/intuitivenipple) gid: (1013/1013) cmd: php-fcgi-wrapper
target uid/gid (1014/1013) mismatch with directory (0/0) or program (0/0)

The first error is caused because 'php-fcgi-wrapper' is a symbolic link to /usr/bin/php-cgi and suexec doesn't allow sym-links.

The second error is caused because the directory and the executable do not have owner and group that match the ones set in the site's VirtualHost configuration (/etc/apache2/sites-available/domain.net.conf):

 <virtualhost domain.net="">SuexecUserGroup "#1014" "#1013"</virtualhost> 

The suexec program has settings built in when it is compiled to prevent it being reconfigured to avoid the security restrictions it is designed to enforce.

If you are using Virtualmin (or more accurately, not using /var/www/ as the root for your virtual domains) you will need to build a custom version of apache's suexec to adjust those built-in settings. You can view them like this:

$ sudo /usr/lib/apache2/suexec -V
 -D AP_DOC_ROOT="/var/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="www-data"
 -D AP_LOG_EXEC="/var/log/apache2/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=100
 -D AP_USERDIR_SUFFIX="public_html"

We need to change to APDOCROOT="/home" for Virtualmin.

Install the tools we need:

$ sudo apt-get install build-essential binutils

Create a directory to keep source-code separate and then fetch the source for apache2.2-common (which contains the suexec code):

$ mkdir SourceCode
$ cd SourceCode
$ sudo  apt-get  build-dep apache2.2-common
$ apt-get source apache2.2-common
Reading package lists... Done
Building dependency tree       
Reading state information... Done
NOTICE: 'apache2' packaging is maintained in the 'Svn' version control system at:
svn://svn.debian.org/pkg-apache
Need to get 6485kB of source archives.
Get: 1 http://archive.ubuntu.com gutsy/main apache2 2.2.4-3build1 (dsc) [1235B]
Get: 2 http://archive.ubuntu.com gutsy/main apache2 2.2.4-3build1 (tar) [6366kB]
Get: 3 http://archive.ubuntu.com gutsy/main apache2 2.2.4-3build1 (diff) [118kB]
Fetched 6485kB in 3s (1849kB/s)
gpg: Signature made Thu 04 Oct 2007 19:28:33 BST using DSA key ID 0A0AC927
gpg: Can't check signature: public key not found
dpkg-source: extracting apache2 in apache2-2.2.4
dpkg-source: unpacking apache2_2.2.4.orig.tar.gz
dpkg-source: applying ./apache2_2.2.4-3build1.diff.gz

Check the Apache 2.2 documentation for details of all the suexec configure options and also Linode-member Internat's guide to rebuilding the apache2.2-common Debian/Ubuntu package.

Move into the source-code directory and configure for our custom requirements:

$ cd  apache2-2.2.4
$ ./configure --prefix=/usr --enable-suexec --with-suexec-caller=www-data --with-suexec-userdir=public_html --with-suexec-docroot=/home --with-suexec-uidmin=100 --with-suexec-gidmin=100 --with-suexec-logfile=/var/log/apache2/suexec.log --with-suexec-safepath='/usr/local/bin:/usr/bin:/bin'

The configure script is responsible for checking that the host PC has all the tools and code-library headers installed. If configure reports an error and mentions a missing library, then you need to install the development headers for that library. Usually the package name has the -devel suffix so, for example, if "libsomething" is missing, the first thing to try is

$ sudo apt-get install libsomething-devel

If this doesn't solve it, search for the correct development library name using:

$ apt-cache search libsomething

If you still can't find it, try a search engine or look at the Ubuntu package repositories.

Assuming configure completed successfully you should see:

...
config.status: creating support/apxs
config.status: creating support/apachectl
config.status: creating support/dbmmanage
config.status: creating support/envvars-std
config.status: creating support/log_server_status
config.status: creating support/logresolve.pl
config.status: creating support/phf_abuse_log.cgi
config.status: creating support/split-logfile
config.status: creating build/rules.mk
config.status: creating build/pkg/pkginfo
config.status: creating build/config_vars.sh
config.status: creating include/ap_config_auto.h
config.status: executing default commands

With everything configured we can build the package:

$ make suexec

Assuming make completes without errors, check that suexec was built and has the correct configuration:

$ ls  support/suexec
support/suexec
$ sudo support/suexec -V
 -D AP_DOC_ROOT="/home"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="www-data"
 -D AP_LOG_EXEC="/var/log/apache2/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=100
 -D AP_USERDIR_SUFFIX="public_html"

Now we need to back-up the installed suexec and put this new version in its place:

$ sudo mv /usr/lib/apache2/suexec /usr/lib/apache2/suexec-var-www
$ sudo cp support/suexec /usr/lib/apache2/suexec
$ sudo chown root:www-data /usr/lib/apache2/suexec
$ sudo chmod 4750 /usr/lib/apache2/suexec

Now that suexec is ready it is time to configure the virtual domains. The directory structure is usually something like this:

/home/domain.net/

/home/domain.net/logs/

/home/domain.net/public_html/

/home/domain.net/cgi-bin/

/home/domain.net/domains/

To those we'll add conf/ (for custom php.ini) and lib/ (for files accessible to php-cgi but outside the web-root).

/home/domain.net/conf/

/home/domain.net/lib/

As an example the pastebin package configuration and code libraries would be installed in lib/.

You will need to repeat the following steps for each virtual domain that needs FastCGI access to PHP (modifying base path and user/group settings for each). The result is that each virtual domain's CGI scripts run as the correct user. See the following article for how to add these values to the Virtualmin domain templates so new domains are created with PHP enabled.

To execute the CGI properly the executable, and the directory it is in, must have the same user and group as those set in the site's SuexecUserGroup statement (referred to earlier). The usual way to assure this is to set SuexecUserGroup to match the user and group of the home directory of the user.

The user's home directory and all directories below it should already meet those requirements so we can install a script in cgi-bin/ that will call the /usr/bin/php-cgi executable.

Change to the user's home directory and create the directories:

$ cd /home/ <virtual-domain-user>$ mkdir conf
$ mkdir lib
$ mkdir -p cgi-bin/php5-default</virtual-domain-user> 

Create conf/php.ini with this content. Make sure to adjust the paths to match the domain:

include_path = ".:/home/intuitivenipple.net/lib"
open_basedir "/home/intuitivenipple.net:/tmp"

Create the script cgi-bin/php5-default/php-fcgi-wrapper with the following contents:

#!/bin/sh
# Wrapper for PHP-fcgi
# This wrapper can be used to define settings before launching the PHP-fcgi binary.

# Define the path to php.ini. This defaults to /etc/phpX/cgi.
export PHPRC=/home/intuitivenipple.net/conf

# Define the number of PHP child processes that will be launched. 
# This is low to control memory usage on a server that might launch
# these processes for lots of domains.
# Leave undefined to let PHP decide.
export PHP_FCGI_CHILDREN=1

# Maximum requests before a process is stopped and a new one is launched
export PHP_FCGI_MAX_REQUESTS=5000

# Launch the PHP CGI binary
# This can be any other version of PHP which is compiled with FCGI support.
exec /usr/bin/php5-cgi

Change the PHPRC path to match the user.

Make sure the directories and the script have the correct user and group ID. Replace and with your virtual domain's user and group respectively:

$ sudo chown -R <user>: <group>cgi-bin/php5-default
$ sudo chown -R <user>: <group>conf
$ sudo chown -R <user>: <group>lib</group></user></group></user></group></user> 

You can use these same steps to install other CGI scripts.

Now the virtual domain's Apache configuration needs a block of directives adding that will activate the FastCGI PHP handler.

Many guides and tutorials show this done on a per-server basis by adding a file to /etc/apache2/conf.d/. The file is often called php-fcgid.conf.

That file will work fine with moduser (allows access to user's publichtml via http://server.domain.net/~user) but won't work with virtual domains where the CGI script has to be owned by the SuexecUserGroup of each Virtual Host.

If you have that already installed in /etc/apache2/conf.d/ you should consider removing it and also deleting the default FastCGI directories at /var/www/fcgi-bin.d/.

Add the following block of directives to the virtual domain's Apache configuration file. The files are usually in the directory /etc/apache2/sites-available/.

For my site, the file is /etc/apache2/sites-available/intuitivenipple.net.conf

The file will start something like:

 <virtualhost 67.18.187.60:80="">SuexecUserGroup "#1014" "#1013"
 ServerName intuitivenipple.net
 ServerAlias www.intuitivenipple.net</virtualhost> 

Ensure the SuexecUserGroup IDs are correct. Here, they are specified as the UID and GID numbers rather than the names (saves Apache time having to look them up). You can get them like this:

$ grep intuitivenipple /etc/passwd
intuitivenipple:x:1014:1013::/home/intuitivenipple.net:/bin/sh

The first number is the UID, the second is the GID. You can cross-reference the GID to its name like this:

$ grep 1013 /etc/group
intuitivenipple:x:1013:www-data

This shows that the group has www-data as a member. That is the identity that Apache runs as.

Now add the FastCGI conditional statements to the end of the virtual domain configuration file, inserting them in front of the closing directive, so it looks like this:

 <ifmodule !mod_php4.c=""><ifmodule !mod_php4_filter.c=""><ifmodule !mod_php5.c=""><ifmodule !mod_php5_filter.c=""><ifmodule !mod_php5_hooks.c=""><ifmodule mod_actions.c=""><ifmodule mod_alias.c=""><ifmodule mod_mime.c=""><ifmodule mod_fcgid.c=""># Define a new handler "php-fcgi" for ".php" files, plus the action that must follow
          AddHandler php-fcgi .php
          Action php-fcgi /fcgi-bin/php-fcgi-wrapper

          # Define alias "/fcgi-bin/". The action above is using this value, which means that
          # you could run another "php5-cgi" command by just changing this alias
          Alias /fcgi-bin/ /home/intuitivenipple.net/cgi-bin/php5-default/

          # Turn on the fcgid-script handler for all files within the alias "/fcgi-bin/"
          <location fcgi-bin="">SetHandler fcgid-script
           Options +ExecCGI</location> 
          # ensure no access to the script source code
          ReWriteEngine On
          ReWriteRule ^/fcgi-bin/[^/]*$ / [PT]</ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule> 

Make sure you set the Alias path to the correct directory! E.g.

Alias /fcgi-bin/ /home/domain.net/cgi-bin/php5-default/

Save the file then restart Apache:

$ sudo /etc/init.d/apache2 restart

Add a simple PHP test file to the web-root:

$ echo "" > public_html/info.php
$ chown <user>: <group>public_html/info.php</group></user> 

You can test it from a browser or even from the command line using wget to ensure the server returns a 200 OK response:

$  wget -O - http://domain.net/info.php | head
--21:59:07--  http://domain.net/info.php
           => `-'
Resolving domain.net... 10.1.2.3
Connecting to domain.net|10.1.2.3|:80... connected.
HTTP request sent, awaiting response... 200 OK

If you see the PHP configuration reported in your browser, starting with something like "PHP Version 5.2.3-1ubuntu6.2", then you've successfully installed SuExec protected FastCGI access to PHP 5.

Remember to repeat the per-virtual-domain steps for each domain that requires PHP support. You can automate that to some degree by adding the directories and files to the /etc/skel/ directory so when a user is created they are copied and permissions set correctly.

If you're working with sub-domains you can copy the parent's cgi-bin directory to the sub-domain (assuming the parent already has the PHP CGI script installed!):

$ pwd
/home/domain.net

$ cp -a cgi-bin domains/subdomain.domain.net/

and then add the FastCGI configuration directives to the sub-domain's apache configuration by editing /etc/apache2/sites-available/subdomain.domain.net.conf to add the Fast CGI directives as described previously.

Make sure to set the Alias path correctly. For sub-domains it is of the form

Alias /fcgi-bin/ /home/domain.net/domains/subdomain.domain.net/cgi-bin/php5-default/

And of course, reload the configuration once more:

$ sudo /etc/init.d/apache2 reload

If you find any mistakes in this guide please report them here and I'll amend this article.

31 Replies

To automate the configuration for all new domains you can configure the Virtualmin default Apache template and add to the /etc/skel/ directory.

In Virtualmin:
4. go to System Settings > Server Templates

  1. Select the Default Settings template

  2. choose Edit Template Section Apache website
    In the Directives and settings for new websites text-area add the following lines to the end of the existing template text:

 <ifmodule !mod_php4.c=""><ifmodule !mod_php4_filter.c=""><ifmodule !mod_php5.c=""><ifmodule !mod_php5_filter.c=""><ifmodule !mod_php5_hooks.c=""><ifmodule mod_actions.c=""><ifmodule mod_alias.c=""><ifmodule mod_mime.c=""><ifmodule mod_fcgid.c=""># Define a new handler "php-fcgi" for ".php" files, plus the action that must follow
          AddHandler php-fcgi .php
          Action php-fcgi /fcgi-bin/php-fcgi-wrapper

          # Define alias "/fcgi-bin/". The action above is using this value, which means that
          # you could run another "php5-cgi" command by just changing this alias
          Alias /fcgi-bin/ ${HOME}/cgi-bin/php5-default/

          # Turn on the fcgid-script handler for all files within the alias "/fcgi-bin/"
          <location fcgi-bin="">SetHandler fcgid-script
           Options +ExecCGI</location></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule> 

Notice how the alias uses a variable:

Alias /fcgi-bin/${HOME}/cgi-bin/php5-default/

Save that change and then open a terminal to the server and add the cgi-bin and PHP directories and script to /etc/skel/:

$ sudo mkdir -p  /etc/skel/cgi-bin/php5-default
$ sudo mkdir /etc/skel/conf
$ sudo mkdir /etc/skel/lib

Create the shell script /etc/skel/cgi-bin/php5-default/php-fcgi-wrapper with these contents:

#!/bin/sh
# Wrapper for PHP-fcgi
# This wrapper can be used to define settings before launching the PHP-fcgi binary.

# Define the path to php.ini. This defaults to /etc/phpX/cgi.
export PHPRC=${HOME}/conf

# Define the number of PHP child processes that will be launched. 
# This is low to control memory usage on a server that might launch
# these processes for lots of domains.
# Leave undefined to let PHP decide.
export PHP_FCGI_CHILDREN=1

# Maximum requests before a process is stopped and a new one is launched
export PHP_FCGI_MAX_REQUESTS=5000

# Launch the PHP CGI binary
# This can be any other version of PHP which is compiled with FCGI support.
exec /usr/bin/php5-cgi

Create the /etc/skel/conf/php.ini file:

include_path = ".:${HOME}/lib"
open_basedir "${HOME}:/tmp"

Set the correct permissions on the files:

$ sudo chmod 750 /etc/skel/cgi-bin/php5-default/php-fcgi-wrapper
$ sudo chmod 750 /etc/skel/conf/php.ini

After creating a new user check that the installed /home//cgi-bin/php5-default/php-fcgi-wrapper and /home//conf/php.ini have had ${HOME} expanded correctly to the absolute path. If not, correct it.

$ cd /home/username
$ NEWHOME="$(pwd)"
$  sed  -ibak -e "s,\${HOME},${NEWHOME}," cgi-bin/php5-default/php-fcgi-wrapper
$  sed  -ibak -e "s,\${HOME},${NEWHOME}," conf/php.ini

This is because when installing from the skeleton files the system has the option of whether or not to expand shell variables in the files, and by default it doesn't (otherwise .profile and others would be a total mess!).

That should be sufficient to ensure all new domains have PHP FastCGI enabled automatically.

You have no idea how much i love you right now..

Umm some things that might be worth changing..

on http://blog.our-files.com/?p=6 i have reference to how to actually build and repackage apache with the new suexec compoonents..

so for some wierd reason i get the following.

Not Found

The requested URL /fcgi-bin/php-fcgi-wrapper/index.php was not found on this server.

 <virtualhost *="">ServerName leela.home.our-lan.com
        ServerAlias www.leela.home.our-lan.com
        ServerAdmin [email protected]
        SuexecUserGroup hostingu2 hostingg12
        DocumentRoot /home/hosting/domains/home.our-lan.com/www
        <directory>Options FollowSymLinks
                AllowOverride None</directory> 
        ErrorLog /home/hosting/domains/home.our-lan.com/logs/apache.error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
        LogLevel warn

        CustomLog /home/hosting/domains/home.our-lan.com/logs/apache.log combined
        ServerSignature Off
 <ifmodule mod_fcgid.c=""># Define a new handler "php-fcgi" for ".php" files, plus the action that must follow
          AddHandler php-fcgi .php
          Action php-fcgi /fcgi-bin/php-fcgi-wrapper

          # Define alias "/fcgi-bin/". The action above is using this value, which means that
          # you could run another "php5-cgi" command by just changing this alias
          Alias /fcgi-bin/ /home/hosting/domains/home.our-lan.com/cgi-bin/php5-default
        <location fcgi-bin="">SetHandler fcgid-script
                Options +ExecCGI</location> 
#</ifmodule> 
          # Turn on the fcgid-script handler for all files within the alias "/fcgi-bin/"</virtualhost> 

find . returns the following

./cgi-bin
./cgi-bin/php5-default
./cgi-bin/php5-default/php-fcgi-wrapper
./www
./www/index.php
./subdomain
./conf
./conf/apache.home.our-lan.com.conf
./conf/php.ini
./logs
./logs/apache.error.log
./logs/apache.log

(note ive removed some entries for the mail directories and so forth

leela:/home/hosting/domains/home.our-lan.com/conf# cat php.ini
include_path = ".:/home/hosting/domains/home.our-lan.com/lib"
open_basedir = "/home/hosting/domains/home.our-lan.com:/tmp"

Anything else i havnt done right?

It looks like the problem is the missing / on the end of:

Alias /fcgi-bin/ /home/hosting/domains/home.our-lan.com/cgi-bin/php5-default 

In case it isn't, I'll leave my earlier ideas here too for you to work with.

It looks like a RewriteRule that isn't tight enough, but I don't see one in the VirtualHost container and you have AllowOverride None (which rules out .htaccess).

However, I discovered recently whilst using RewriteRule that Alias also appears to use it - path translations for fcgi appeared in the RewriteLog.

So, try enabling RewriteLog in the VirtualHost container:

RewriteEngine on
RewriteLog /home/hosting/domains/home.our-lan.com/logs/rewrite.log
RewriteLogLevel 9

Restart/reload Apache, access the URL, and then review what (if anything) is in logs/rewrite.log.

Also, show the relevant entries from the error.log since when fcgi has problems it is quite verbose.

Well the rewrite module wasnt even enabled. But ive added it now..

But rewrite.log is still empty..

leela:/etc/apache2/mods-enabled# ls
actions.load          authz_host.load  dir.load          rewrite.load
alias.load            authz_user.load  env.load          setenvif.load
auth_basic.load       autoindex.load   fcgid.conf        status.load
authn_file.load       cgid.conf        fcgid.load        suexec.load
authz_default.load    cgid.load        mime.load
authz_groupfile.load  dir.conf         negotiation.load

All enabled modules..

You replied too quickly! I added another observation at the top of my response when I noticed Alias missing the trailing /

Excelent, that did indeed fix the problem, another question though, what is stopping the user navigating to the fcgi-bin/php5-default/php-fcgi-wrapper and viewing that file, cause i just checked that i could do that and i could indeed get to that file from the webpage.. might need to add a limit/deny to that..

I'm not sure what other rules you've got, possibly some RewriteRules, but on my pastebin at least, requesting that path reports:

GET /fcgi-bin/php5-default/php-fcgi-wrapper HTTP/1.1

HTTP/1.x 404 Not Found

Found a really interesting way of running php as a cgi, while allowing the web data to be placed in /home/user/pubilc_html, without having to recomplie apache.

http://jp-larocque.livejournal.com/49475.html

Might be useful, and seems to work quite well.

sorry.

i typed the url wrong

try navigating to /fcgi-bin/php-fcgi-wrapper and it outputs the wrapper code…

For the record, i have no rewrite rules at all or enabled.

Thanks for spotting that. An additional ReWriteRule is needed. I'll document it here and also edit the original article so no-one gets confused as this thread develops.

/etc/apache/sites-available/domain.net.conf

RewriteEngine on
RewriteLog /home/domain.net/logs/rewrite.log
RewriteLogLevel 9
RewriteRule ^/([a-z0-9]+)$ /pastebin.php?show=$1 [L]
ReWriteRule ^/fcgi-bin/[^/]*$ / [PT]

This is the code I use for pastebin. Note I've added the [ L ] flag to the main pastebin RewriteRule to end processing there if that rule matches.

If not, and the url begins with /fcgi-bin/ it is rewritten to the root of the domain ( / ) and then passed back through [ PT ] the rewrite engine as a genuine request would appear.

Hi TJ.

You know me (I'll send you a PM), I was searching the net for how to install suexec for PHP as its been perplexing me for months. I started reading your guide and then realised part way down it was written by you. A small world eh?

Anyway I am still absolutely stuck. I'm running centos so I dont think all the packages are the same and my dev machine is php4, live is php5. I havent been able to get anywhere with either of them. I've followed all the guides as closely as I can and it always comes back to the same thing.

That is, my suexec.log is empty and the following php script

Always displays "apache"

I am really stuck and beginning to go round in circles and tear my hair out. Any help would be immeasurably appreciated. I think I have followed so many different guides that my install is a bit messed up now.

Incidentally, I AM using webmin and virtualmin but I didnt include those search terms when I came accross this page!

Thanks a lot,

Tim

@timnp:

You know me (I'll send you a PM)
Reading that made me spit water over the screen, I laughed so much. It'd be a poor state of affairs if I forgot you! :roll:

Email me so we can arrange a time to chat because I don't think our MSN schedules are currently synchronised.

I just tried that but it bounces on both the addresses I tried. Do you want to PM me the one you use these days?

If the site suddenly starts reporting 500 Server Error and /home//logs/error.log looks similar to this:

[Wed Mar 19 00:31:38 2008] [warn] (104)Connection reset by peer: mod_fcgid: read data from fastcgi server error.
[Wed Mar 19 00:31:38 2008] [error] [client 1.2.3.4] Premature end of script headers: php-fcgi-wrapper

it is probable that your distribution has updated the apache2 package and replaced your /usr/lib/apache2/suexec file.

You can check by looking at the APDOCROOT it reports. It should be "/home":

$ sudo /usr/lib/apache2/suexec -V
 -D AP_DOC_ROOT="/var/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="www-data"
 -D AP_LOG_EXEC="/var/log/apache2/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=100
 -D AP_USERDIR_SUFFIX="public_html" 

Oops - wrong!

You will need to download the source code for the installed version of apache2-common and follow the first article's instructions up until you've installed the corrected version to /usr/lib/apache2/suexec.

Those instructions start with:

$ mkdir SourceCode
$ cd SourceCode
$ sudo  apt-get  build-dep apache2.2-common 

Hello,

I am looking for someone to set up this configuration for me. I have a newly create linode. Right now the linode is Ubuntu 7.1, but I can change it to another distribution if necessary. I will need the VM configured to optimized to run Magento.

See here

http://www.magentocommerce.com/blog/com … rformance/">http://www.magentocommerce.com/blog/comments/performance-is-key-notes-on-magentos-performance/

You're site is a great help. I'm a perl guy - I'm even the maintainer for DBD::mysql. I do like PHP though, and have been given the task lately of implementing PHP offerings at Lycos for Tripod.com users. I have been trying like mad to find a way to set openbasedir per user. We don't use UIDs/useraccounts on tripod. We have a big NFS directory, each user logged in has a directory. I want to limit what users can open with openbasedir to this directory. We're using fastcgi with a wrapper script, which works fine. I was trying to do:

exec /usr/bin/php-cgi -d openbasedir=$REDIRECTsite_root

Didn't work. It seemed to ignore -d. I would run php-cgi -d open_basedir=/path/to/user by command line and it worked, but in CGI mode, it didn't.

Then I saw on this wonderful site

open_basedir= ${HOME}/…

In the php.ini file. This made me realize I could do

openbasedir= ${REDIRECTsite_root}

Which works great!

Thanks mucho muchly!

I'm trying to model linode on my local server before actually purchase one, but I've got some problem with setting up php-cgi mode. I have followed all how-to here, and managed to run simple php site (with phpinfo() in the code) but when I transfered my existing typo3 based site, it shows me empty-body page. "tail /var/log/apache2/error.log" shows following:

[Tue Feb 10 11:17:47 2009] [info] Server built: May  2 2008 16:35:55
[Tue Feb 10 11:17:47 2009] [debug] worker.c(1740): AcceptMutex: sysvsem (default: sysvsem)
[Tue Feb 10 11:17:47 2009] [debug] proxy_util.c(1670): proxy: grabbed scoreboard slot 0 in child 19378 for worker proxy:reverse
[Tue Feb 10 11:17:47 2009] [debug] proxy_util.c(1689): proxy: worker proxy:reverse already initialized
[Tue Feb 10 11:17:47 2009] [debug] proxy_util.c(1761): proxy: initialized worker 0 in child 19378 for (*) min=0 max=25 smax=25
[Tue Feb 10 11:17:47 2009] [debug] proxy_util.c(1670): proxy: grabbed scoreboard slot 0 in child 19407 for worker proxy:reverse
[Tue Feb 10 11:17:47 2009] [debug] proxy_util.c(1689): proxy: worker proxy:reverse already initialized
[Tue Feb 10 11:17:47 2009] [debug] proxy_util.c(1761): proxy: initialized worker 0 in child 19407 for (*) min=0 max=25 smax=25
[Tue Feb 10 11:17:52 2009] [info] mod_fcgid: server /hsphere/local/home/ywamrest/ywamrestenas.se/cgi-bin/php5-default/php-fcgi-wrapper(19437) started
[Tue Feb 10 11:17:55 2009] [info] mod_fcgid: server /hsphere/local/home/ywamrest/ywamrestenas.se/cgi-bin/php5-default/php-fcgi-wrapper(19439) started

access.log shows:````
192.168.0.64 - - [10/Feb/2009:11:14:31 +0000] "GET /fileadmin/templates/ywamrestenas/scripts/functions.js HTTP/1.1" 304 - "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"
192.168.0.64 - - [10/Feb/2009:11:14:31 +0000] "GET /typo3temp/javascript757c080409.js HTTP/1.1" 304 - "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5" 192.168.0.64 - - [10/Feb/2009:11:17:52 +0000] "GET / HTTP/1.1" 200 720 "-" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5" 192.168.0.64 - - [10/Feb/2009:11:17:54 +0000] "GET /typo3temp/stylesheete99aac0be0.css HTTP/1.1" 304 - "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"
192.168.0.64 - - [10/Feb/2009:11:17:54 +0000] "GET /fileadmin/templates/ywamrestenas/scripts/newsfader.js HTTP/1.1" 304 - "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"
192.168.0.64 - - [10/Feb/2009:11:17:54 +0000] "GET /stylesheet.spp HTTP/1.1" 200 7607 "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"
192.168.0.64 - - [10/Feb/2009:11:17:54 +0000] "GET /rte.spp HTTP/1.1" 200 2690 "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"
192.168.0.64 - - [10/Feb/2009:11:17:54 +0000] "GET /objects.spp HTTP/1.1" 200 2589 "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"
192.168.0.64 - - [10/Feb/2009:11:17:55 +0000] "GET /fileadmin/templates/ywamrestenas/scripts/functions.js HTTP/1.1" 304 - "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"
192.168.0.64 - - [10/Feb/2009:11:17:55 +0000] "GET /typo3temp/javascript_757c080409.js HTTP/1.1" 304 - "http://ywamrestenas.base/" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121622 Ubuntu/8.10 (intrepid) Firefox/3.0.5"

````
So, it does look like everything should be all right, but the same site is working perfectly on the other server with php5-mode. What am I doing wrong here?

check that you have all the modules properly enabled.

and can you paste the output of the suexec logs?

where to find suexec logs? I have passed some logs in previous post

Ok sorry, I have found suexec.log in the same directory that error.log and access.log located but suexec.log is empty.

After a few refreshes, suexec.log shows following: [2009-02-24 13:27:39]: uid: (1000/ywamrest) gid: (1000/1000) cmd: php-fcgi-wrapper [2009-02-24 13:27:43]: uid: (1000/ywamrest) gid: (1000/1000) cmd: php-fcgi-wrapper

By the way, header of the page is generated, but no content or anything related to content.

Slightly offtopic, but if I were to configure apache in the way described in this thread, how would that affect the use of perl/python?

Cheers.

Someone appears to have acquired your tutorial

http://www.unixguru.biz/?p=40

I had a bit of time on the weekend and I thought I'd give hybinet's script a run on Debian Lenny.

First thing that came up was I didn't have permission to access /fcgi-bin/wrapper/test.php on the server. After a day and a bit, I found I had to change the following bit of code from this:

 <location fcgi-bin="">SetHandler fcgid-script
                Options +ExecCGI</location> 

to this:

 <location fcgi-bin="">SetHandler fcgid-script
             Options +ExecCGI
             Order allow,deny
             Allow from all</location> 

I don't know why it didn't work. No one else in this tread reported a problem with not having the Order and Allow. (might just be my server setup or a Lenny thing)

Next it spat errors in suexec.log. Something about terminating. Tracked that one down to the spaces in front of the wrapper text in the build script:

cat > $dirn/cgi-bin/php5-fcgi-wrapper/wrapper <<- _EOF1_
    #!/bin/sh
    export PHPRC=$dirn/conf
    export PHP_FCGI_CHILDREN=1
    export PHP_FCGI_MAX_REQUESTS=5000
    exec /usr/bin/php5-cgi
_EOF1_

Changing the script to this fixed it:

cat > $dirn/cgi-bin/php5-fcgi-wrapper/wrapper <<- _EOF1_
#!/bin/sh
export PHPRC=$dirn/conf
export PHP_FCGI_CHILDREN=1
export PHP_FCGI_MAX_REQUESTS=5000
exec /usr/bin/php5-cgi
_EOF1_

The last thing that turned up was:

/etc/init.d/apache2 reload

needed to be:

/etc/init.d/apache2 restart

Really nice script now that I have it working.

If anyone knows the answer to why I found what I did when no one else did, let me know.

Does anyone know how to get this working with the current version on Virtualmin. Virtualmin does the custom SUEXEC stuff now but it installs apach2-mpm-prefork and libapach2-mod-php5 and if I switch to apach2-mpm-worker the browser offers php files for download. If I leave it all this gets ignored and nothing changes.

If it's offering php files to download then the handler's aren't set correctly.

You probably need

AddHandler application/x-httpd-php .php

Somewhere in your apache configuration.

Do you have any idea where it should go. I'm relatively new to this.

I've just upgraded the server from Ubuntu Hardy 8.04 LTS to Lucid 10.04 LTS.

As part of that process the apache web-server was updated and lost the custom-built suexec which caused the apache2 server to fail to start.

On investigation I found that Ubuntu now carries a custom suexec package that can be configured via a configuration file rather than re-compiling the suexec binary.

Install the custom package:

sudo apt-get install apache2-suexec-custom

The man page says:
> This version of suexec reads a config file on every execution … If suexec is called by a user with name ’username’, it will look into /etc/apache2/suexec/username for configuration. If the file does not

exist, suexec will abort. By creating several config files, you can allow several different apache run users to use suexec.
The configuration file requirements are:
> The first line in the file is used as the document root (/var/www in the standard suexec) and the second line in the file is used as the suffix that is appended to users’ home directories (public_html in standard suexec).

If any of the lines is commented out (with #), suexec will refuse the corresponding type of request. It is recommended to comment out the userdir suffix if you don’t need it.
There is an example file at /etc/apache2/suexec/www-data:

/var/www
public_html/cgi-bin
# The first two lines contain the suexec document root and the suexec userdir
# suffix. Both features can be disabled separately by prepending a # character.
# This config file is only used by the apache2-suexec-custom package.

In my scenario, using VirtualMin, and without wanting to change the existing configuration for all the virtual servers, I added a custom suexec configuration file for each virtual server user account:

/home
public_html

The man-page Security recommendation says:
> Do not set the document root to a path that includes users’ home directories (like /home or /var)…
but due to the way the server is configured by VirtualMin I am happy to allow this without being concerned too much. I'll investigate this further when I'm sure the upgraded server services are all working as expected.

Hello everyone!

I make all from first post and I use apache2-suexec-custom module, but I see this error````
[2012-01-06 03:30:22]: uid: (1001/siteuser) gid: (1001/siteuser) cmd: php5
[2012-01-06 03:30:22]: command not in docroot (/usr/lib/cgi-bin/php5)

in /var/log/apache2/suexec.log and 500 Internal Server Error in front page…

What am I doing wrong?

cat /etc/apache2/suexec/siteuser /home/www publichtml

````
cat /etc/apache2/sites-enabled/site | grep -v '#'
 <virtualhost 127.0.0.1:8080="">ServerName   site:8080
        ServerAlias  www.site
        ServerAdmin  "[email protected]"
        SuexecUserGroup site_user site_user
        DocumentRoot /home/www/site_user/public_html
        CustomLog  /var/log/apache2/site/access_log combined
        ErrorLog  /var/log/apache2/site/error_log
        <ifmodule mod_ssl.c="">SSLEngine off</ifmodule> 
        <directory home="" www="" site_user="" public_html="">Options +ExecCGI
        AllowOverride All
        <ifmodule sapi_apache2.c="">php_admin_flag engine on
                php_admin_flag safe_mode off
                php_admin_value open_basedir "/home/www/site_user/:/tmp"</ifmodule> 
        <ifmodule mod_php5.c="">php_admin_flag engine on
                php_admin_flag safe_mode off
                php_admin_value memory_limit 512M
                php_admin_value open_basedir "/home/www/site_user/:/tmp"</ifmodule> 
        <ifmodule mod_fcgid.c=""><files ~="" (\.fcgi)="">SetHandler fcgid-script
                        Options +FollowSymLinks +ExecCGI</files></ifmodule></directory> 

 <ifmodule !mod_php4.c=""><ifmodule !mod_php4_filter.c=""><ifmodule !mod_php5.c=""><ifmodule !mod_php5_filter.c=""><ifmodule !mod_php5_hooks.c=""><ifmodule mod_actions.c=""><ifmodule mod_alias.c=""><ifmodule mod_mime.c=""><ifmodule mod_fcgid.c="">AddHandler php-fcgi .php
          Action php-fcgi /fcgi-bin/php-fcgi-wrapper

          Alias /fcgi-bin/ /home/www/site_user/cgi-bin/php5-default/

          <location fcgi-bin="">SetHandler fcgid-script
           Options +ExecCGI</location> 
          ReWriteEngine On
          ReWriteRule ^/fcgi-bin/[^/]*$ / [PT] 
          RewriteLog /home/www/site_user/logs/rewrite.log
          RewriteLogLevel 9</ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></ifmodule></virtualhost> 

P.S. sorry for my bad English =)

UPD:

Goddamn! I previously configured the apache2.conf

 <directory home="" www="">AddHandler fcgid-script .php
   FCGWrapper /usr/lib/cgi-bin/php5 .php
   Options +ExecCGI</directory> 

Now, I commented out this and it worked! Thank you again!

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct