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 :

Download http://www.suphp.org/download/suphp-0.7.1.tar.gz
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
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/mod_suphp.so
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.

[global]
;Path to logfile
logfile=/var/log/httpd/suphp.log

;Loglevel
loglevel=info

;User Apache is running as
; MANDATORY
webserver_user=apache

; 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
docroot=/

;Path to chroot() to before executing script
;chroot=/home

; Security options
allow_file_group_writeable=true
allow_file_others_writeable=true
allow_directory_group_writeable=true
allow_directory_others_writeable=true

; 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
check_vhost_docroot=false

; 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
;userdir_overrides_usergroup=true

; 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.
;paranoid_uid_check=true
;paranoid_gid_check=true

;Send minor error messages to browser
errors_to_browser=false

;PATH environment variable
env_path="/bin:/usr/bin"

;Umask to set, specify in octal notation
umask=0022

; Minimum UID
;min_uid=100

; Minimum GID
;min_gid=100

; 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.
;full_php_process_display=true

[handlers]
;Handler for php-scripts
application/x-httpd-php="php:/usr/bin/php-cgi"
application/x-httpd-php4="php:/usr/php4/bin/php-cgi"
application/x-httpd-php5="php:/usr/bin/php-cgi"

;Handler for CGI-scripts
;x-suphp-cgi="execute:!self"

[phprc_paths]
;Uncommenting these will force all requests to that handler to use the php.ini
;in the specified directory regardless of suPHP_ConfigPath settings.
;application/x-httpd-php=/usr/local/lib/
;application/x-httpd-php4=/usr/local/php4/lib/
;application/x-httpd-php5=/usr/local/lib/

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.pl index.plx index.ppl index.cgi index.jsp index.js index.jp 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

Scenario:

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:

/scripts/pkgacct

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

/scripts/restorepkg

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

Scenario:

 

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 http://poptop.sourceforge.net/yum/stable/rhel5/pptp-release-current.noarch.rpm
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 172.16.36.1" >> /etc/pptpd.conf
echo "remoteip 172.16.36.2-254" >> /etc/pptpd.conf
echo "ms-dns 8.8.8.8" >> /etc/ppp/options.pptpd
echo "ms-dns 8.8.4.4" >> /etc/ppp/options.pptpd

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

iptables -t nat -A POSTROUTING -s 172.16.36.0/24 -j SNAT --to-source ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk 'NR==1 { print $1}'
iptables -A FORWARD -p tcp --syn -s 172.16.36.0/24 -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

Scenario:

Site1 : www.site.com
Site2 : shop.site2.com

The idea is to make a proxy redirect so if I access www.site.com/shop to be redirected to shop.site2.com 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/site.com/conf a file called vhost.conf that contains:

ProxyRequests off
Order deny,allow
Allow from all

ProxyPass /shop http://shop.site2.com
ProxyPassReverse /shop http://shop.site2.com
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 www.site.com/shop/ you should be redirected to shop.site2.com. 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 10.0.0.1 netmask 255.255.255.0 up

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

ip addr add 10.0.0.0/24 dev xenbr0

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


iptables -t nat  -A POSTROUTING -s 10.0.0.0/255.255.255.0 -j MASQUERADE

iptables -I RH-Firewall-1-INPUT -s 10.0.0.0/24 -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 (http://wiki.centos.org/Manuals/ReleaseNotes/CentOS5.6 ) 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.

 


#!/bin/bash

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
fi

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
else

 

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

 

http://wiki.centos.org/Manuals/ReleaseNotes/CentOS5.6