Installing mod_suphp

Usually if you add a simple VirtualHost and set the DocumentRoot into on /home/ then its possible for some files not to be owned by that (e.g: uploaded images via web interface, php sessions..etc).

A solution for this problem is to install mod_suphp which will make Apache to write in /home/ with permissions. To install mod_suphp :

tar zxvf suphp-0.7.1.tar.gz
cd suphp-0.7.1
yum install httpd-devel
./configure --with-apxs=/usr/sbin/apxs --with-apache-user=httpd --with-logfile=/var/log/httpd/suphp.log --with-setid-mode=paranoid --sysconfdir=/etc --with-apr=/usr/bin/apr-1-config --with-php=/usr/bin/php-cgi --enable-SUPHP_USE_USERGROUP=yes
make install
cd /etc/httpd/conf.d/
mv php.conf php.conf.bk

Then create suphp.conf and put in it:

LoadModule suphp_module modules/
suPHP_Engine on
AddType application/x-httpd-php5 .php5 .php4 .php .php3 .php2 .phtml

suPHP_AddHandler application/x-httpd-php5

Then create /etc/suphp.conf and put in it:

; This file is parse anew by suPHP for each request
; rather than being loaded once.

;Path to logfile


;User Apache is running as

; Path all scripts have to be in
; This works as a prefix when a trailing slash is not specified.
; e.g. /home will match /home /home2 /home3 etc While /home/ will only match /home/
; Changing this to a more specific path will improve security

;Path to chroot() to before executing script

; Security options

; Check whether script is within DOCUMENT_ROOT
; Does NOT perform this check on included scripts.
; i.e. include_once("/test3.php"); works even though it's in the root directory
; Changing this to true will improve security but make all php userdir requests fail

; Allow the user and group specified by a ~userdir request to override the
; suPHP_UserGroup directive inside the source virtualhost
; Changing this to false will improve security but make some types of php userdir
; requests fail

; suPHP Paranoid mode checks that the target script UID and GID match
; the UID and GID of the user running the script. To disable these
; checks change the following values to false. Without these checks, mod_suphp
; is effectively running in "Force" mode.

;Send minor error messages to browser

;PATH environment variable

;Umask to set, specify in octal notation

; Minimum UID

; Minimum GID

; Normally suPHP only displays the PHP binary in process lists (ps aux).
; Setting this option to 'true' will cause suPHP to display both the
; PHP binary and the script filename.

;Handler for php-scripts

;Handler for CGI-scripts

;Uncommenting these will force all requests to that handler to use the php.ini
;in the specified directory regardless of suPHP_ConfigPath settings.

After this make sure that the VirtualHost contains :

suPHP_UserGroup user user

SuexecUserGroup user user

Also /etc/httpd/conf/httpd.conf should contain:

DirectoryIndex index.html.var index.htm index.html index.shtml index.xhtml index.wml index.perl index.plx index.ppl index.cgi index.jsp index.js index.php4 index.php3 index.php index.phtml default.htm default.html home.htm index.php5 Default.html Default.htm home.html

Finally do a service httpd restart

Check /var/log/httpd/suphp.log and error_log for possible errors. In my case I noticed this:

“[Fri Apr 22 14:36:55 2011] [warn] Mismatch between target UID (501) and UID (48) of file “/home/arpart/public_html/index.php”

Which means that some files were not owned by . Use chown -R user.user /home/user to fix the problem.

Transferring a lot of files over the network


These days one customer asked me to perform a migration from a shared Hostgator account to two different servers (one for DB and one for the files). Usually for these situations I use rsync but this case was tricky since Hostgator kills the ssh connection if a process takes to long to complete..and since I had to transfer like 1 million files it took 5-10 minute for rsync to pass the “building file list” stage.
I tried different tricks like doing a:

find $HOME/public_html > $HOME/files

in order to store in a file all the file/dir names and then use rsync’s --files-from parameter but without luck. In the end I noticed that I was being disconnected when transferring large files (>2GB). I’ve excluded the involved files by using :

rsync --stats -P -avz --exclude="error_log" --exclude="user_db.sql" --size-only -e 'ssh -o ServerAliveInterval=30 -o TCPKeepAlive=no -o ServerAliveInterval=15' www/ user@remote_location:/home/user/public_html/

–size-only = skip files that match in size

Other trick that I found is using the –bwlimit to limit the transfer speed to a value in KBPS.

For the larger files I’ve used the classic way (FTP).

Howto backup or restore individual cPanel accounts from command line

Since cPanel already have scripts to backup/restore individual accounts all you have to do is to:


This will create a backup of and in order to restore it run:


Note that you will have to run this commands as root and in order to restore you need to be in the directory where the backup is stored.

Yum and RPM Tricks

This applies to Centos 5.6 but most likely it works on any rpm based distro.

1. It happened many times to mess the permissions of a file and services not to work properly. In order to get fixed I run :

rpm -qf /path/to/file

rpm -ql Lists all files from a package.

This should show the package that contains the modified file. Then I run :

rpm --setperms

Also this command should show a list of modified files within a package:

rpm -V

2. To view the Changelog:

rpm -q --changelog | less

3. View package based on repo:

rpm -qa release="*rf*"

4. Extract just one File:

rpm2cpio logrotate-1.0-1.i386.rpm |cpio -ivd etc/logrotate.conf

5. Query Package Install Order and Dates

rpm -qa --last >~/RPMS_by_Install_Date

6. Query Available Packages from a Repo

Setting a PPTP VPN in CentOS 5.6



Setting a PPTP VPN in Centos. I’m using the following commands in order to set the VPN:



yum remove -y pptpd ppp
iptables --flush POSTROUTING --table nat
iptables --flush FORWARD
rm -rf /etc/pptpd.conf
rm -rf /etc/ppp

rpm -Uvh
yum --enablerepo=poptop-stable install pptpd

mknod /dev/ppp c 108 0
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "mknod /dev/ppp c 108 0" >> /etc/rc.local
echo "echo 1 > /proc/sys/net/ipv4/ip_forward" >> /etc/rc.local
echo "localip" >> /etc/pptpd.conf
echo "remoteip" >> /etc/pptpd.conf
echo "ms-dns" >> /etc/ppp/options.pptpd
echo "ms-dns" >> /etc/ppp/options.pptpd

pass=openssl rand 6 -base64
if [ "$1" != "" ]
then pass=$1
read -p "User: " user
echo "${user} pptpd ${pass} *" >> /etc/ppp/chap-secrets

iptables -t nat -A POSTROUTING -s -j SNAT --to-source ifconfig | grep 'inet addr:'| grep -v '' | cut -d: -f2 | awk 'NR==1 { print $1}'
iptables -A FORWARD -p tcp --syn -s -j TCPMSS --set-mss 1356
service iptables save

chkconfig iptables on
chkconfig pptpd on
service iptables start
service pptpd start

echo "VPN username is ${user}, VPN password is ${pass}"

Using mod_proxy in Plesk to redirect to a different site


Site1 :
Site2 :

The idea is to make a proxy redirect so if I access to be redirected to and keep the URL in the browser.
This can be done either by using mod_rewrite (if both sites are on the same server) or by using mod_proxy. In my case I had to do this on a Plesk server.

I’ve created in /var/www/vhosts/ a file called vhost.conf that contains:

ProxyRequests off
Order deny,allow
Allow from all

ProxyPass /shop
ProxyPassReverse /shop
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1

Order allow,deny
Allow from all

Then I ran:

/usr/local/psa/admin/bin/websrvmng -a -v

Verify httpd.include to see if there is any Include directive.

Now if you go to you should be redirected to Notice the trailing slash after (../shop/). That needs to be there otherwise it won’t load the images properly.

This can be fixed by adding in vhost.conf a Rewrite rule like:
RewriteEngine on
RewriteRule ^/shop$ /shop/ [R]

Setting a local network on Xenserver

After installing Xenserver 5.5 or 5.6 you will need to define additional IPs that your VMs will use. Usually your provider will give you a range that you can use. But what do you do when you do not want to pay additional $$$ just for a couple of routable ips?

In my case I only have one public IP that is set on interface xenbr0 interface (bridged from eth0). In order to make my VMs to access the Internet I had to add an alias interface, something like :

ifconfig xenbr0:0 netmask up

I will consider my private LAN from where the VMs will get IPs. Additionally I route all traffic from to xenbr0 using :

ip addr add dev xenbr0

Now if you add an VM and set an IP from the range you should be able to ping the address. In order to reach the internet I also had to :

iptables -t nat  -A POSTROUTING -s -j MASQUERADE

iptables -I RH-Firewall-1-INPUT -s -j ACCEPT

service iptables save


Last thing is to modify /etc/sysctl.conf and enable ip_forward among other settings. This is how my config looks like:

net.ipv4.ip_forward = 1
net.ipv4.conf.default.proxy_arp = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.xenbr0.send_redirects = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
kernel.sysrq = 1
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 4294967295
kernel.shmall = 268435456
vm.dirty_ratio = 5
kernel.printk = 4 4 1 4


Centos 5.6 templates for XenServer 5.5/5.6

As you probably know already CentOS 5.6 is out ( ) and since Xenserver 5.5/5.6 is missing this templates I had to add them manually.  I’m using this script that clones the CentOS 5.3 template.



CENTOS=$(xe template-list name-label=CentOS 5.3 --minimal)
if [[ -z $CENTOS ]] ; then
echo "Cant find CentOS 5.3 32bit template, are you on XenServer 5.5 or higher?"
exit 1

distro="CentOS 5.6"
arches=("32-bit" "64-bit")

for arch in ${arches[@]} ; do
echo "Attempting $distro ($arch)"
if [[ -n $(xe template-list name-label="$distro ($arch)" params=uuid --minimal) ]] ; then
echo "$distro ($arch)" already exists, Skipping


NEWUUID=$(xe vm-clone uuid=$CENTOS new-name-label="$distro ($arch)")
xe template-param-set uuid=$NEWUUID other-config:install-methods=http,ftp,nfs
echo "Success"
echo "Done"