How To Set Up Apache2 With mod_fcgid And PHP5 On Mandriva 2009.1
Version 1.0
Author: Falko Timme
Follow me on Twitter
This tutorial describes how you can install Apache2 with mod_fcgid and PHP5 on Mandriva 2009.1. mod_fcgid is a compatible alternative to the older mod_fastcgi. It lets you execute PHP scripts with the permissions of their owners instead of the Apache user.
I do not issue any guarantee that this will work for you!
1 Preliminary Note
I'm using a Mandriva 2009.1 server in this tutorial with the hostname server1.example.com and the IP address 192.168.0.100.
I will create two Apache vhosts in this tutorial, www.example1.com and www.example2.com, to demonstrate the usage of mod_fcgid.
2 Installing Apache2/mod_fcgi/PHP5
First we update our package database:
urpmi.update -a
We can install Apache2, mod_fcgid, and PHP5 as follows (mod_fcgid requires apache-mpm-worker instead of apache-mpm-prefork, so if apache-mpm-prefork is currently installed, the Apache modules that rely on it will get removed, such as apache-mod_php):
urpmi apache-mpm-worker apache-mod_fcgid php-fcgi
[root@server1 ~]# urpmi apache-mpm-worker apache-mod_fcgid php-fcgi
The following packages have to be removed for others to be upgraded:
apache-mod_perl-2.0.4-5mdv2009.1.x86_64
(due to conflicts with apache-mpm-worker-2.2.11-10.5mdv2009.1.x86_64)
apache-mod_php-5.2.9-1mdv2009.1.x86_64
(due to conflicts with apache-mpm-worker[>= 2.2.8]) (y/N) <-- y
To satisfy dependencies, the following packages are going to be installed:
Package Version Release Arch
(medium "Main Updates")
apache-base 2.2.11 10.5mdv2009.1 x86_64
apache-mod_ssl 2.2.11 10.5mdv2009.1 x86_64
apache-modules 2.2.11 10.5mdv2009.1 x86_64
apache-mpm-prefork 2.2.11 10.5mdv2009.1 x86_64
apache-mpm-worker 2.2.11 10.5mdv2009.1 x86_64
php-fcgi 5.2.9 6.2mdv2009.1 x86_64
(medium "Contrib")
apache-mod_fcgid 2.2 6mdv2009.1 x86_64
6MB of disk space will be freed.
977KB of packages will be retrieved.
Proceed with the installation of the 7 packages? (Y/n) <-- Y
Next we open /etc/php.ini...
vi /etc/php.ini
... and add the line cgi.fix_pathinfo = 1 right at the end of the file:
[...] cgi.fix_pathinfo = 1 |
Then restart Apache:
/etc/init.d/httpd restart
3 Creating Vhosts For www.example1.com And www.example2.com
I will now create two vhosts, www.example1.com (with the document root /var/www/web1/web) and www.example2.com (with the document root /var/www/web2/web). www.example1.com will be owned by the user and group web1, and www.example2.com by the user and group web2.
First we create the users and groups:
groupadd web1
groupadd web2
useradd -s /bin/false -d /var/www/web1 -m -g web1 web1
useradd -s /bin/false -d /var/www/web2 -m -g web2 web2
chmod 755 /var/www/web1
chmod 755 /var/www/web2
Then we create the document roots and make them owned by the users/groups web1 resp. web2:
mkdir -p /var/www/web1/web
chown web1:web1 /var/www/web1/web
mkdir -p /var/www/web2/web
chown web2:web2 /var/www/web2/web
We will run PHP using suExec; suExec's document root is /var/www, as the following command shows:
/usr/sbin/suexec -V
[root@server1 ~]# /usr/sbin/suexec -V
-D AP_DOC_ROOT="/var/www"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec_log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_SUEXEC_UMASK=077
-D AP_UID_MIN=100
-D AP_USERDIR_SUFFIX="public_html"
[root@server1 ~]#
Therefore we cannot call the PHP binary (/usr/bin/php-fcgi) directly because it is located outside suExec's document root. As suExec does not allow symlinks, the only way to solve the problem is to create a wrapper script for each web site in a subdirectory of /var/www; the wrapper script will then call the PHP binary /usr/bin/php-fcgi. The wrapper script must be owned by the user and group of each web site, therefore we need one wrapper script for each web site. I'm going to create the wrapper scripts in subdirectories of /var/www/php-fcgi-scripts, e.g. /var/www/php-fcgi-scripts/web1 and /var/www/php-fcgi-scripts/web2.
mkdir -p /var/www/php-fcgi-scripts/web1
mkdir -p /var/www/php-fcgi-scripts/web2
vi /var/www/php-fcgi-scripts/web1/php-fcgi-starter
#!/bin/sh PHPRC=/etc/ export PHPRC export PHP_FCGI_MAX_REQUESTS=5000 export PHP_FCGI_CHILDREN=8 exec /usr/bin/php-fcgi |
vi /var/www/php-fcgi-scripts/web2/php-fcgi-starter
#!/bin/sh PHPRC=/etc/ export PHPRC export PHP_FCGI_MAX_REQUESTS=5000 export PHP_FCGI_CHILDREN=8 exec /usr/bin/php-fcgi |
The PHPRC line contains the directory where the php.ini file is located (i.e., /etc/ translates to /etc/php.ini). PHP_FCGI_MAX_REQUESTS is the maximum number of requests before an fcgid process is stopped and a new one is launched. PHP_FCGI_CHILDREN defines the number of PHP children that will be launched.
The php-fcgi-starter scripts must be executable, and they (and the directories they are in) must be owned by the web site's user and group:
chmod 755 /var/www/php-fcgi-scripts/web1/php-fcgi-starter
chmod 755 /var/www/php-fcgi-scripts/web2/php-fcgi-starter
chown -R web1:web1 /var/www/php-fcgi-scripts/web1
chown -R web2:web2 /var/www/php-fcgi-scripts/web2
Now we create the Apache vhosts for www.example1.com and www.example2.com. Add the following two vhosts at the end of /etc/httpd/conf/httpd.conf:
vi /etc/httpd/conf/httpd.conf
[...] NameVirtualHost *:80 <VirtualHost *:80> ServerName www.example1.com ServerAlias example1.com ServerAdmin [email protected] DocumentRoot /var/www/web1/web/ <IfModule mod_fcgid.c> SuexecUserGroup web1 web1 PHP_Fix_Pathinfo_Enable 1 <Directory /var/www/web1/web/> Options +ExecCGI AllowOverride All AddHandler fcgid-script .php FCGIWrapper /var/www/php-fcgi-scripts/web1/php-fcgi-starter .php Order allow,deny Allow from all </Directory> </IfModule> # ErrorLog /var/log/apache2/error.log # CustomLog /var/log/apache2/access.log combined ServerSignature Off </VirtualHost> <VirtualHost *:80> ServerName www.example2.com ServerAlias example2.com ServerAdmin [email protected] DocumentRoot /var/www/web2/web/ <IfModule mod_fcgid.c> SuexecUserGroup web2 web2 PHP_Fix_Pathinfo_Enable 1 <Directory /var/www/web2/web/> Options +ExecCGI AllowOverride All AddHandler fcgid-script .php FCGIWrapper /var/www/php-fcgi-scripts/web2/php-fcgi-starter .php Order allow,deny Allow from all </Directory> </IfModule> # ErrorLog /var/log/apache2/error.log # CustomLog /var/log/apache2/access.log combined ServerSignature Off </VirtualHost> |
Make sure you fill in the right paths (and the correct user and group in the SuexecUserGroup lines).
Reload Apache afterwards:
/etc/init.d/httpd reload