This article pertains to installing PHP from source code, along with the
suhosin hardening patch and extension, and the
SuPHP PHP wrapper on a CentOS 5.x Linux system.
REMEMBER Always make backups!
Necessary RPM's
The following non-PHP related RPM's were installed:
httpd httpd-devel mysql mysql-server mysql-devel
mod_ssl mod_auth_mysql perl-DBD-MySQL
In my case, I replaced the stock CentOS RPM's for MySQL with the one's from
dev.mysql.com:
MySQL-client-community-5.1.22-0.rhel5.i386.rpm
MySQL-devel-community-5.1.22-0.rhel5.i386.rpm
MySQL-server-community-5.1.22-0.rhel5.i386.rpm
MySQL-shared-compat-5.1.22-0.rhel5.i386.rpm
Optional RPM's
I consider these to be mandatory on a modern web server for the mere fact, that nearly all web developers utilize third party web applications that make use of them. Graphics utilities like GD and ImageMagick are used by most forum & bulletin board applications, and even security software such as CAPTCHA's may use GD and/or ImageMagick. Other additions include mod_python & mod_perl for those web developers that want cutting edge scripting abilities. With "
cutting edge" in mind, I also have a habit of including the following (and all their dependencies):
mod_perl mod_python libtidy libtidy-devel
gd gd-devel gd-progs ImageMagick ImageMagick-devel ImageMagick-perl
Download PHP, suhosin & SuPHP, then patch
- I setup a directory on a large partition for my own compiles at /storage/compile/ and store my downloads in /storage/tarballs/, however, you can place the downloads wherever you see fit. At my place of employment, we store tarballs & source to be compiled in /usr/src/SCRIPTS/.
- Untar/gunzip PHP, suhosing extensions & the patch file. Place the patch file outside of the PHP source directory:
mv suhosin-patch-5.2.5-0.9.6.2.patch /storage/compile/
- Copy the suhosin extension source code into the PHP source tree's ext/suhosin directory:
cp -pr suhosin-0.9.22 /storage/compile/php-5.2.5/ext/suhosin
- Patch PHP with the suhosing patch:
patch -p 1 -i ../suhosin-patch-5.2.5-0.9.6.2.patch
- If successful, you should see something similar to:
patching file TSRM/TSRM.h
patching file TSRM/tsrm_virtual_cwd.c
patching file TSRM/tsrm_virtual_cwd.h
patching file Zend/Makefile.am
patching file Zend/Zend.dsp
...
patching file sapi/apache/mod_php5.c
patching file sapi/apache2filter/sapi_apache2.c
patching file sapi/apache2handler/sapi_apache2.c
patching file sapi/cgi/cgi_main.c
patching file sapi/cli/php_cli.c
patching file win32/build/config.w32
Configure & Compile PHP
- Change to the PHP source directory:
cd /storage/compile/php-5.2.5/
./buildconf --force
./configure --prefix=/usr --sysconfdir=/etc --with-config-file-path=/etc \
--enable-cgi --enable-force-cgi-redirect --enable-discard-path --with-mysql=/usr \
--enable-mbstring --with-bz2 --with-curl --enable-bcmath --enable-exif --with-gd \
--enable-gd-native-ttf --with-gettext --with-png-dir=/usr --with-jpeg-dir=/usr \
--with-freetype-dir=/usr --with-zlib --enable-calendar --with-openssl --with-gmp \
--enable-ftp --enable-magic-quotes --with-mcrypt --with-mhash --enable-ctype \
--enable-tidy --enable-dom --with-libxml-dir=/usr --enable-libxml --enable-xml \
--enable-xmlreader --enable-xmlwriter --enable-zip --enable-shmop --enable-wddx \
--with-pear --enable-pdo --with-pdo-mysql=/usr --disable-embedded-mysqli \
--with-mysqli=/usr/bin/mysql_config --enable-inline-optimization --enable-suhosin
make
make test
make install
- Copy the php.ini file to /etc:
cp ./php.ini-recommended /etc/php.ini
- Edit /etc/php.ini to suit. I recommend the following changes:
Change:
short_open_tag = Off
To:
short_open_tag = On
Change (lets you see full error messages):
log_errors_max_len = 1024
To:
log_errors_max_len = 0
Change (security):
magic_quotes_gpc = Off
To:
magic_quotes_gpc = On
Change:
upload_max_filesize = 2M
To:
upload_max_filesize = 16M
Change (I've seen this needed on many app'z, like [http://gallery.sf.net Gallery]):
allow_url_include = Off
To:
allow_url_include = On
Change (Set to your timezone, as found in /usr/share/zoneinfo/):
;date.timezone =
To:
date.timezone = America/Phoenix
Install SuPHP
- Untar/gunzip SuPHP source code, and go into the directory
cd /storage/compile/suphp-0.6.2
- HACK: Edit the following with your favorite editor:
nano src/apache2/mod_suphp.c
- Find line 324 & 325
Change Line 324:
... suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, ACCESS_CONF, ...
To:
... suPHP_AddHandler", suphp_handle_cmd_add_handler, NULL, RSRC_CONF | ACCESS_CONF, ...
Change Line 325:
... suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, ACCESS_CONF, ...
To:
... suPHP_RemoveHandler", suphp_handle_cmd_remove_handler, NULL, RSRC_CONF | ACCESS_CONF, ...
./configure --prefix=/usr --sysconfdir=/etc --enable-checkpath \
--with-apr=/usr --with-apxs=/usr/sbin/apxs --with-setid-mode=paranoid --with-min-uid=100 \
--with-min-gid=500 --with-apache-user=apache --with-logfile=/var/log/httpd/suphp_log
make
make install
- Copy configuration file to /etc:
cp doc/suphp.conf-example /etc/suphp.conf
- Create mod_suphp.conf file for apache:
cd /etc/httpd/conf.d/
nano -w mod_suphp.conf (or your editor of choice: vi, joe, elvis, etc)
# This is the Apache server configuration file providing suPHP support.
# It contains the configuration directives to instruct the server how to
# serve php pages while switching to the user context before rendering.
LoadModule suphp_module modules/mod_suphp.so
# This option tells mod_suphp if a PHP-script requested on this server (or
# VirtualHost) should be run with the PHP-interpreter or returned to the
# browser "as it is".
suPHP_Engine on
# To use suPHP to parse PHP-Files
AddHandler x-httpd-php .php .php5 .php4 .php3 .phtml
# This option tells mod_suphp which path to pass on to the PHP-interpreter
# (by setting the PHPRC environment variable).
# Do *NOT* refer to a file but to the directory the file resides in.
#
# E.g.: If you want to use "/path/to/server/config/php.ini", use "suPHP_Config
# /path/to/server/config".
#
# If you don't use this option, PHP will use its compiled in default path.
suPHP_ConfigPath /etc
# If you compiled suphp with setid-mode "force" or "paranoid", you can
# specify the user- and groupname to run PHP-scripts with.
# Example: suPHP_UserGroup foouser bargroup
#
# -NOTE- WE SET THIS ON A PER VHOST SETTING. DON'T SET HERE
#
# suPHP_UserGroup apache apache
# This option tells mod_suphp to handle requests with the type .
# Please note this only works, if an action for the handler is specified
# in the suPHP configuration file.
suPHP_AddHandler x-httpd-php
# This option tells mod_suphp to NOT handle requests with the type .
# suPHP_RemoveHandler
Change:
logfile=/var/log/suphp.log
To:
logfile=/var/log/httpd/suphp_log
Change:
webserver_user=wwwrun
To:
webserver_user=apache
Change:
docroot=/
To:
docroot=/var/www/virtual/
Change (if you're not concerned with security):
errors_to_browser=false
To:
errors_to_browser=true
Change:
umask=0077
To:
umask=0133
Change:
min_gid=100
To:
min_gid=500
Change:
x-httpd-php=php:/usr/bin/php
To:
x-httpd-php=php:/usr/bin/php-cgi
Editing Apache and suPHP Configs
- First, I want to stop the loading of mod_php, or the PHP Apache module, if it exists, so it does not load on startup. To do this, rename the php module config file:
mv /etc/httpd/conf.d/php.conf /etc/httpd/conf.d/php.conf.orig2007
- Next, edit /etc/httpd/conf/httpd.conf file. In this example, we'll comment out a few global defaults, and make a few minor changes:
Change (For security reasons):
ServerTokens OS
To:
ServerTokens Prod
Change to your liking:
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000
Example:
StartServers 10
MinSpareServers 10
MaxSpareServers 25
ServerLimit 1024
MaxClients 1024
MaxRequestsPerChild 4000
Change (if uncommented):
ServerName www.example.com:80
To:
#ServerName www.example.com:80
Change:
DirectoryIndex index.html index.html.var
To:
DirectoryIndex index.php index.html index.htm index.html.var
Change:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
To: (comment it out)
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
Change:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
To: (comment out example, copy and change end from "combinedio" to "combined")
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combined
Change:
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
To: (comment out global scope)
#ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
Change:
AllowOverride None
Options None
Order allow,deny
Allow from all
To: (comment out)
#
# AllowOverride None
# Options None
# Order allow,deny
# Allow from all
#
Now add NameVirtualHost & VirtualHost directives. Note that I have included "
suPHP_UserGroup userid groupid", required for suPHP to work properly
AND I've also enabled SuEXEC for CGI scripts. Example:
NameVirtualHost ip.add.re.ss:80
ServerAdmin webmaster@int.domain
ServerName web.int.domain
ServerAlias *.web.int.domain
SuexecUserGroup userid groupid
suPHP_UserGroup userid groupid
ErrorLog logs/web.int.domain-error_log
CustomLog logs/web.int.domain-access_log combined
DocumentRoot /var/www/virtual/default_vhost/htdocs
Options -Indexes SymLinksifOwnerMatch
AllowOverride Options FileInfo AuthConfig Limit
ScriptAlias /cgi-bin/ "/var/www/virtual/default_vhost/cgi-bin/"
AllowOverride None
Options SymLinksifOwnerMatch
Order allow,deny
Allow from all
# Personal addition to disable TRACE method in Apache
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
Editing /etc/php.ini
Change the following under [sessions]:
session.save_path=/tmp/sess
Create the directory if necessary, and type:
chmod 1777 /tmp/sess
Creating a new /tmp if partition
If a /tmp partition was not created on a Linux system, you can go about creating one with the following:
cd /dev
# Create 500MB file for our /tmp partition. If you need
# more or less space, make count size larger or smaller.
dd if=/dev/zero of=tmpMnt bs=1024 count=500000
# Make an EXT3 filesystem for our tmpMnt file
/sbin/mke2fs -j /dev/tmpMnt
# Backup your /tmp dir- I had mysql.sock file that I
# needed to recreate the symbolic link for. Other
# programs may use it to store cache files or whatever.
cd /
cp -r /tmp /tmp_backup
# Mount the new /tmp filesystem with noexec, nosuid
# and read/write, and set permissions.
mount -o loop,noexec,nosuid,rw /dev/tmpMnt /tmp
chmod 1777 /tmp
# Copy everything back to new /tmp and remove backup
cp -r /tmp_backup/* /tmp/
rm -rf /tmp_backup
REFERENCES
http://www.phoenixwing.com/wiki/Stock_CentOS_with_PHP_SuPHP_suhosin#Download_PHP.2C_suhosin_.26_SuPHP.2C_then_patch