suPHP for Apache , The painless way...
What is suPHP:
Normally in a webserver setup, virtual hosting setup, users have their virtual hosts directories, in which they upload their web content. Definitely the virtual hosts directories are owned by each virtual host owner individually. However, the problem comes when they create a file through PHP scripts. The file gets created as owner and group apache (apache:apache) . Once such a file is created, the site owner is not able to change ownership, permissions of this file. Nor he can delete it or rename it. And now this file becomes a pain and a nightmare to handle. Such problems are commonly being experienced by webmasters setting up Joomla CMS on their sites. The configuration.php file gets created as (apache:apache) and then the problem of it’s maintenance starts. The solution is to run PHP scripts / programs as the user who owns the php file, which is the webmaster / FTP user account. Apache comes with SuExec, but it works only with CGI programs. The solution to our problem is suPHP.
Homepage: http://www.suphp.org
It was a real pain setting suPHP, because the documentation which comes with it, or on the website, is not clear.
I have used the following links to get help for suPHP.
http://www.lecaptain.org/?p=12
http://forum.swsoft.com/showthread.php?t=49426
http://www.howtoforge.coapache2_suphp_php4_php5_p2
Before we start, it should be noted that most of the errors related to suphp are mentioned at http://www.suphp.org/FAQ.html, which you should open in a web browser, separately.
RPM method:
Download suphp from http://dag.wieers.com/rpm/packages/mod_suphp/mod_suphp-0.6.2-1.rf.src.rpm
wget http://dag.wieers.com/rpm/packages/mod_suphp/mod_suphp-0.6.2-1.rf.src.rpm
[root@kworkhorse downloads]# rpmbuild --rebuild mod_suphp-0.6.2-1.rf.src.rpm
Checking for unpackaged file(s): /usr/lib/rpm/check-files /var/tmp/mod_suphp-0.6.2-1.rf-root
Wrote: /usr/src/redhat/RPMS/x86_64/mod_suphp-0.6.2-1.rf.x86_64.rpm
Wrote: /usr/src/redhat/RPMS/x86_64/mod_suphp-debuginfo-0.6.2-1.rf.x86_64.rpm
rpm -ivh /usr/src/redhat/RPMS/x86_64/mod_suphp-0.6.2-1.rf.x86_64.rpm
[root@kworkhorse etc]# rpm -ql mod_suphp
/etc/httpd/conf.d/suphp.conf
/etc/suphp.conf
/usr/lib64/httpd/modules/mod_suphp.so
/usr/sbin/suphp
/usr/share/doc/mod_suphp-0.6.2
/usr/share/doc/mod_suphp-0.6.2/AUTHORS
/usr/share/doc/mod_suphp-0.6.2/COPYING
/usr/share/doc/mod_suphp-0.6.2/ChangeLog
/usr/share/doc/mod_suphp-0.6.2/NEWS
/usr/share/doc/mod_suphp-0.6.2/README
/usr/share/doc/mod_suphp-0.6.2/doc
/usr/share/doc/mod_suphp-0.6.2/doc/CONFIG
/usr/share/doc/mod_suphp-0.6.2/doc/INSTALL
/usr/share/doc/mod_suphp-0.6.2/doc/LICENSE
/usr/share/doc/mod_suphp-0.6.2/doc/README
/usr/share/doc/mod_suphp-0.6.2/doc/apache
/usr/share/doc/mod_suphp-0.6.2/doc/apache/CONFIG
/usr/share/doc/mod_suphp-0.6.2/doc/apache/INSTALL
/usr/share/doc/mod_suphp-0.6.2/doc/apache/README
/usr/share/doc/mod_suphp-0.6.2/doc/suphp.conf-example
vi /etc/suphp.conf
[global]
logfile=/var/log/httpd/suphp_log
loglevel=info
webserver_user=apache
docroot=/
env_path=/bin:/usr/bin
umask=0022
min_uid=500
min_gid=48
; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser
errors_to_browser=true
[handlers]
;Handler for php-scripts
x-httpd-php=php:/usr/bin/php-cgi
;Handler for CGI-scripts
x-suphp-cgi=execute:!self
Disable the original PHP 5 module:
[root@kworkhorse etc]# mv /etc/httpd/conf.d/php.conf /etc/httpd/conf.d/php.conf.disabled
[root@kworkhorse etc]# vi /etc/httpd/conf.d/suphp.conf
LoadModule suphp_module modules/mod_suphp.so
suPHP_Engine on
AddHandler x-httpd-php .php
AddHandler x-httpd-php .php .php4 .php3 .phtml
#suPHP_UserGroup apache apache
suPHP_AddHandler x-httpd-php
I have the following VirtualHost definition in my apache config file:-
<VirtualHost * :80>
ServerAdmin webmaster@example.com
DocumentRoot /var/www/vhosts/example.com
ServerName www.example.com
suPHP_UserGroup webmaster apache
< /VirtualHost >
Note that my example.com directory and the index.php file within it are owned by webmaster:apache
[root@kworkhorse etc]# ls -l /var/www/vhosts/
total 4
drwxr-xr-x 2 webmaster apache 4096 2008-06-04 00:18 example.com
[root@kworkhorse etc]# ls -l /var/www/vhosts/example.com/
total 4
-rw-r–r– 1 webmaster apache 37 2008-06-04 00:18 index.php
Service httpd restart
Open a browser and try opening the www.example.com site (whatever is your virtualhost).
You should get the following , as a result of successful execution of suphp for your virtualhost.
[root@kworkhorse ~]# tail -f /var/log/httpd/suphp_log
[Wed Jun 04 10:43:18 2008] [info] Executing “/var/www/vhosts/example.com/index.php” as UID 501, GID 48
File Creation Test: (Last Test, for which we undergo all this pain):
Create a file through php script. It SHOULD get created as user webmaster and group apache (if your setup is successful).
Here is the code you can put in a file, say createfile.php in your documentroot. Note it is a MUST to setup the ownership and permission of your php file as the same owner / group of your document root.
vi /var/www/vhosts/example.com/createfile.php
< ?php
$file=”testfile.html”;
$fp=fopen($file,”w”);
#echo “This script is being run as user (ID) : “. fileowner(‘createfile.php’) . “< br>”;
echo “The owner of the script being run : get_current_user : “ . get_current_user() . “< br>”;
echo “The UID of the user: int getmyuid ( void ) : “ . getmyuid() . “< br>”;
if (fwrite($fp,”< h1>Hello</ h1>”))
echo “File created.”;
else
echo “File not created !!!”;
fclose($fp);
?>
chown webmaster:apache /var/www/vhosts/example.com/createfile.php
Run this file through browser and you should see a file created as testfile.html in your documentroot . Just for the sake of completeness of this document, the contents of that file would be a word “Hello”.
As you can see from the file list below, the file is successfully created in my documentroot, with correct ownership and permissions.
[root@kworkhorse etc]# ls -l /var/www/vhosts/example.com/
total 12
-rw-r–r– 1 webmaster apache 247 2008-06-04 11:08 createfile.php
-rw-r–r– 1 webmaster apache 37 2008-06-04 00:18 index.php
-rw-r–r– 1 webmaster apache 14 2008-06-04 11:07 testfile.html
You should get the following , as a result of successful execution of suphp for your this file.
[root@kworkhorse ~]# tail -f /var/log/httpd/suphp_log
[Wed Jun 04 11:07:55 2008] [info] Executing “/var/www/vhosts/example.com/createfile.php” as UID 501, GID 48
Alhumdulillah.
Now the Source Code method:
Last thing. Install the latest suphp.
Latest version is suphp-0.6.3 , available at http://www.suphp.org
Download and unpack it in a directory. Then before you configure it, you need to fix a small bug in it’s mod_suphp.c file .
Reference: http://www.howtoforge.com/apache2_suphp_php4_php5_p2
Here is how to do it:-
[root@kworkhorse ~]# cd /data/downloads/suphp-0.6.3
[root@kworkhorse suphp-0.6.3]# vi src/apache2/mod_suphp.c
Find the following two lines and change ACCESS_CONF to ?RSRC_CONF | ACCESS_CONF in them:
Original:
AP_INIT_ITERATE(“suPHP_AddHandler”suphp_handle_cmd_add_handler, NULL, ACCESS_CONF, “Tells mod_suphp to handle these MIME-types”),
AP_INIT_ITERATE(“suPHP_RemoveHandler”, suphp_handle_cmd_remove_handler, NULL, ACCESS_CONF,”Tells mod_suphp not to handle these MIME-types”),
Edited:
AP_INIT_ITERATE(“suPHP_AddHandler”, suphp_handle_cmd_add_handler, NULL, RSRC_CONF | ACCESS_CONF, “Tells mod_suphp to handle these MIME-types”),
AP_INIT_ITERATE(“suPHP_RemoveHandler”, suphp_handle_cmd_remove_handler, NULL, RSRC_CONF | ACCESS_CONF, “Tells mod_suphp not to handle these MIME-types”),
If you don’t do the above patch, you will constantly get stupid messages, such as:-
[root@kworkhorse suphp-0.6.3]# service httpd restart
Stopping httpd: [FAILED]
Starting httpd: Syntax error on line 996 of /etc/httpd/conf/httpd.conf:
suPHP_AddHandler not allowed here
[FAILED]
OR, If you have defined it in your /etc/httpd/conf.d/suphp.conf :-
[root@kworkhorse conf.d]# service httpd restart
Stopping httpd: [ OK ]
Starting httpd: Syntax error on line 43 of /etc/httpd/conf.d/suphp.conf:
suPHP_AddHandler not allowed here
[FAILED]
Here goes the package compilation steps:-
./configure
–prefix=/usr
–sysconfdir=/etc
–exec-prefix=/usr
–enable-checkpath
–with-apache-user=”apache”
–with-apr=/usr/bin/apr-1-config
–with-apxs=/usr/sbin/apxs
–with-logfile=/var/log/httpd/suphp_log
–with-min-uid=”500”
–with-min-gid=”48”
–with-php=/usr/bin/php
–with-setid-mode=”paranoid”
make
make install
Now, setup the following files as shown below:-
vi /etc/suphp.conf
[ global]
logfile=/var/log/httpd/suphp_log
loglevel=info
webserver_user=apache
docroot=/
env_path=/bin:/usr/bin
;Umask to set, specify in octal notation (Change it to 0022)
umask=0022
; Minimum UID (your users may / normally start from 500 )
min_uid=500
; Minimum GID (change 100 to 48 for GID of apache )
min_gid=48
; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser
errors_to_browser=true
; Handler for php-scripts (MUST: change the following to php-cgi instead of php)
; x-httpd-php=php:/usr/bin/php
x-httpd-php=php:/usr/bin/php-cgi
;Handler for CGI-scripts
x-suphp-cgi=execute:!self
Setup the suphp to be enabled site-wide. If you want to enable / disable it for a specific virtual host, you can use the suPHP_Engine on/off settings in that particular virtualhost configuration.
[root@kworkhorse etc]# vi /etc/httpd/conf.d/suphp.conf
LoadModule suphp_module modules/mod_suphp.so
suPHP_Engine on
AddHandler x-httpd-php .php
AddHandler x-httpd-php .php .php4 .php3 .phtml
suPHP_AddHandler x-httpd-php
#Don’t enable the following line. It is supposed to work in virtual hosts.
#And each virual host may (WILL) have different user. Group may be same. eg. “suPHP_UserGroup webmaster apache”
#suPHP_UserGroup apache apache
I have the following VirtualHost definition in my apache config file:-
vi /etc/httpd/conf/httpd.conf
< VirtualHost *:80>
ServerAdmin webmaster@example.com
DocumentRoot /var/www/vhosts/example.com
ServerName www.example.com
suPHP_UserGroup webmaster apache
< /VirtualHost>
Note that my example.com directory and the index.php file within it are owned by webmaster:apache
[root@kworkhorse etc]# ls -l /var/www/vhosts/
total 4
drwxr-xr-x 2 webmaster apache 4096 2008-06-04 00:18 example.com
[root@kworkhorse etc]# ls -l /var/www/vhosts/example.com/
total 4
-rw-r–r– 1 webmaster apache 37 2008-06-04 00:18 index.php
Time to disable the default php handler / apache module
[root@kworkhorse ~]# mv /etc/httpd/conf.d/php.conf /etc/httpd/conf.d/php.conf.disabled
service httpd restart
Open a browser and try opening the www.example.com site (whatever is your virtualhost).
You should get the following , as a result of successful execution of suphp for your virtualhost.
[root@kworkhorse ~]# tail -f /var/log/httpd/suphp_log
[Wed Jun 04 10:43:18 2008] [ info] Executing “/var/www/vhosts/example.com/index.php” as UID 501, GID 48
You can use the createfile.php example given in the RPM section of this howto.
Hope it helps solve the ever famous problem of: “My files are being created as apache:apache and I cannot control them anymore!”.
Alhumdulillah. Done.