Remote IP 38.107.179.243 Recorded at 1327711046

CentOS nginx php-fpm apc memcache installation guide

> January 11th, 2012 ---

won’t go into the reasons why you should install nginx, if you’re here, you’ve already decided.
Here’s how I installed nginx and PHP-FPM on CentOS.

Firstly, I got the latest PHP 5.2 tar ball, 5.3 sucks, then the PHP-FPM patch and finally the latest nginx.

wget http://uk3.php.net/get/php-5.2.17.tar.gz/from/uk.php.net/mirror
wget http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz
wget http://nginx.org/download/nginx-0.9.5.tar.gz

Optional: I installed MySQL server aswell. You don’t have to.

yum install mysql-server
/etc/init.d/mysqld start
If you’re on CentOS, don’t forget to finish the MySQL installation

/usr/bin/mysql_secure_installation
Install PHP
Next, some pre-requisites for the PHP & nginx installs. You may not need them all depending on how you configure PHP. Delete/add to suit.

yum install libxml2-devel bzip2-devel curl-devel libjpeg-devel libpng-devel libX11-devel gd-devel libc-client-devel libmcrypt-devel mysql-devel mhash-devel libevent-devel libtool-ltdl-devel
Now some pre-requisites for building the souce

yum install patch gcc make libtool-ltdl libtool
Lets build PHP

tar zxpfv php-5.2.17.tar.gz

gzip -cd php-5.2.17-fpm-0.5.14.diff.gz | patch -d php-5.2.17 -p1

cd php-5.2.17

./configure –enable-fastcgi –enable-fpm –with-mcrypt –with-zlib –enable-mbstring –disable-pdo –with-mysql –with-curl –disable-debug –disable-rpath –enable-inline-optimization –with-bz2 -with-zlib –enable-sockets –enable-sysvsem –enable-sysvshm –enable-mbregex –with-mhash –enable-zip –with-pcre-regex –with-freetype-dir –with-jpeg-dir –enable-zend-multibyte –with-gd –with-libdir=lib64
make
make install
For kicks, we’ll install the MemCache and APC caching extensions, we’ll use them some time.

pecl install memcached apc
Then, copy the php.ini file to its new home, don’t be tempted to copy it elsewhere otherwise it’ll never find itself.

cp php.ini-dist /usr/local/lib/php.ini
If you installed the APC extension, You should add “extension=apc.so” to the bottom of the php.ini

Fix some brain dead exploit in PHP, edit php.ini and change cgi.fix_pathinfo=0
See http://wiki.nginx.org/Pitfalls#FastCGI_Path_in_Script_Name for more information.

I haven’t found a compatible chkconfig style startup script for PHP-FPM yet

echo /etc/init.d/php-fpm start >> /etc/rc.local

Create an unprivileged user for PHP-FPM to run and store data as
groupadd www-data
useradd -g www-data -d /dev/null www-data
That’s it for compiling PHP. The only thing we have left to do is change some settings in the php-fpm conf. Open up /usr/local/etc/php-fpm.conf. Do some searching and change the users who own the processes to www-data, it should look something like;

www-data
www-data
www-data
www-data
I also like to change PHP-FPM to run as a socket, so we don’t have any TCP/IP overhead for extra, extra speed.

/var/run/php-fpm.sock
Installing nginx
We’re compiling the Perl module into nginx for some funky goodness I will cover soon.

yum install pcre-devel pcre
Now, configure nginx

tar zpfvx nginx-0.9.5.tar.gz

cd nginx-0.9.5
./configure –without-mail_pop3_module –without-mail_imap_module –without-mail_smtp_module –with-http_ssl_module –with-http_stub_status_module –with-http_gzip_static_module –with-http_perl_module
make
make install
I stole some config settings for nginx’s fastcgi_params file from http://interfacelab.com/nginx-php-fpm-apc-awesome/

nano /usr/local/nginx/conf/fastcgi_params
And insert the following at the top

fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
We need to make nginx start on boot, I also stole this init script from Linode.

wget https://library.linode.com/web-servers/nginx/installation/reference/init-rpm.sh
mv init-rpm.sh /etc/rc.d/init.d/nginx
chmod +x /etc/rc.d/init.d/nginx
chkconfig –add nginx
chkconfig –level 2345 nginx on
Although it needs some modification to work with our default settings.

nano /etc/init.d/nginx
Change the following lines
nginx=”/usr/local/nginx/sbin/nginx”
NGINX_CONF_FILE=”/usr/local/nginx/conf/nginx.conf”
Now just start them both!

/etc/init.d/nginx start
/etc/init.d/php-fpm start
Simple as!

http://bloke.org/php/installing-nginx-php-fpm-securely-centos/

Drupal in the Cloud: Deploying on Rackspace with Nginx and Boost

> January 10th, 2012 ---

Lately, we have been involved in a project where our clients needed a site capable of serving a large number of anonymous users and a reasonable number of concurrently logged in users. In order to reach these goals, we looked to the cloud. We first got as much caching as possible, since this is relatively simple and goes a long way. We next created a distributed system. This blogs describes how we got it to work. A diagram of our architecture is attached, and the various configurations are summarized at the bottom.

First, the anonymous user caching. Anonymous users all view the same content, so if we cache a static html page, we can serve this page without involving php at all. We are using boost to provide these static pages. And then we have nginx serving these cached pages and acting proxying other requests to Apache. Since nginx can scale without much of a memory hit, it is much better to use nginx to serve large amounts of static files and let apache handle the logged in users and new page requests. Now, for anonymous users, the bottleneck suddenly becomes the network, and on a localhost test, ab records well over 10 thousand hits per second being served by a 2gb rackspace instance.

On to logged in caching. We use APC as an opcode cache. This saves the server from recompiling the php code on every page load. Moreover, the whole thing fits easily in RAM (we typically give APC 128M of ram). This drastically decreases the CPU usage. Logged in users can now browse the site much faster. But we can still only handle a limited number of them. We can do a bit better. Instead of querying MySQL every time we go to the cache, we can store these tables in memory. Here come memcached and the cacherouter module.

Now, if you’ve looked at the nginx conf bellow, you might have noticed that it is also acting as a load balancer. We have Drupal on multiple nodes. The first step in achieving this was putting MySQL on a different node (this does require hardening it up) and having apache live on different machine. However, in order to make sure that user uploaded files and “boosted” cache files are available on all apache servers, we use glusterfs to replicate files accross all machines. We also use glusterfs to replicate the code base so that changes can be made quickly, although we rsync it to the file system since it slows down file operations. The PHP code is not being run from glusterfs.

Putting it all together: the architecture. You can find the attached diagram with the architecture. We are deploying all our servers on rackspace hosting, starting with an Ubuntu Karmic image. There are three types of nodes: load balancers and static file servers which we’ll refer to as nginx nodes, server nodes with apache which we’ll refer to as apache nodes, and the database node(s) which we’ll refer to as mysql nodes.

The nginx nodes have nginx, memcached and glusterfs installed. They serve static files from a shared folder on a glusterfs mount. Any request which is not cached and is not found in the static files will be proxied to the pool of apache nodes. The memcached deamon is part of a pool in which the apache nodes also participate, and which is used by cacherouter to distribute mysql cached queries and the cache tables. The nginx nodes can be replicated for high availability, since the files they are serving are replicated in real time via glusterfs.

The apache nodes have apache with mod_php and php 5.2 installed, as well as glusterfs, apc and memcached. We can spin up new instances quickly and add them to the pool, as once glusterfs is mounted, it will quickly sync up the files from the other nodes as necessary, and be available to receive it’s share of requests. All the Drupal nodes talk to the MySQL node for the database. The MySQL node can also be replicated for high availability.

Deploying rapidly: what is the point of having a distributed architecture in the cloud if we cannot scale quickly? We use puppet to quickly configure a node which has been spun up to the nginx or apache pools.

Wrapping it up: we should be able to follow up soon with a post on performance. Testing we have done so far indicates that the system does scale up quite well. We have also compared rackspace hosting to ec2, and the numbers show that rackspace is much faster for drupal, mostly due to the network latency. We will soon have numbers and graphs to show it all.

Configuring apc: we set the memory size to 128M with a single bin.

Configuring cacherouter: version: 6.x.1.x-dev (vs 6.x.1.0-rc1)
* The dev version had some bug fixes for the memcached engine at the time we installed it
Append following to your Drupal’s settings.php

# Cacherouter
$conf['cache_inc'] = './sites/all/modules/cacherouter/cacherouter.inc';
$conf['cacherouter'] = array(
'default' => array(
'engine' => 'memcached',
'servers' => array(
'web01',
'web02',
'web03',
),
'shared' => TRUE,
'prefix' => '',
'path' => '',
'static' => FALSE,
'fast_cache' => FALSE,
),
);
?>

Configuring boost: most of boost’s default settings are fine. We turned on gzip and enabled css and js caching. We also ignore the htaccess rules, since we use nginx to serve the html files.

Configuring nginx (version 7.62):
in nginx.conf in the “http” section:
upstream apaches {
#ip_hash;
server web01;
server web02;
server web03;
}
?>

in the host conf, in the “server” section:


server {
listen 80;

proxy_set_header Host $http_host;

gzip on;
gzip_static on;
gzip_proxied any;

gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

set $myroot /var/www;

#charset koi8-r;
# deny access to files beginning with a dot (.htaccess, .git, ...)

location ~ ^. {
deny all;
}

location ~ .(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(.php)?|xtmpl)$|^(code-style.pl|Entries.*|Repository|Root|Tag|Template)$ {
deny all;
}

set $boost "";
set $boost_query "_";
if (

$request_method = GET ) {
set $boost G;
}
if (

$http_cookie !~ "DRUPAL_UID") {
set $boost "${boost}D";
}
if (

$query_string = "") {
set $boost "${boost}Q";
}
if ( -

f $myroot/cache/normal/$http_host$request_uri$boost_query$query_string.html ) {
set $boost "${boost}F";
}
if (

$boost = GDQF){
rewrite ^.*$ /cache/normal/$http_host/$request_uri$boost_query$query_string.html break;
}

if ( -f $myroot/cache/perm/$http_host$request_uri$boost_query$query_string.css ) {
set $boost "${boost}F";
}
if (

$boost = GDQF){
rewrite ^.*$ /cache/perm/$http_host/$request_uri$boost_query$query_string.css break;
}

if ( -f $myroot/cache/perm/$http_host$request_uri$boost_query$query_string.js ) {
set $boost "${boost}F";
}
if (

$boost = GDQF){
rewrite ^.*$ /cache/perm/$http_host/$request_uri$boost_query$query_string.js break;
}

location ~* .(txt|jpg|jpeg|css|js|gif|png|bmp|flv|pdf|ps|doc|mp3|wmv|wma|wav|ogg|mpg|mpeg|mpg4|htm|zip|bz2|rar|xls|docx|avi|djvu|mp4|rtf|ico)$ {
root $myroot;
expires max;
add_header Vary Accept-Encoding;
if (-f $request_filename) {
break;
}
if (!-f $request_filename) {
proxy_pass " ">http://apaches";
break;
}
}

location ~* .(html(.gz)?|xml)$ {
add_header Cache-Control no-cache,no-store,must-validate;
root $myroot;
if (-f $request_filename) {
break;
}
if (!-f $request_filename) {
proxy_pass " ">http://apaches";
break;
}
}

location / {
access_log /var/log/nginx/localhost.proxy.log proxy;
proxy_pass " ">http://apaches";
}
}

?>

Configuring glusterfs: (version 3.0.3)
There are two files. glusterfsd holds the local “brick”. glusterfs holds the info on how to mount and use the bricks.

glusterfsd.vol

# Generated by Puppet
volume posix
type storage/posix
option directory ####
end-volume
volume locks
type features

/locks
option mandatory-locks on
subvolumes posix
end-volume
volume iothreads
type performance

/io-threads
option thread-count 16
subvolumes locks
end-volume
volume server

-tcp
type protocol/server
subvolumes iothreads
option transport-type tcp
option auth.login.iothreads.allow ####
option auth.login.####.password ####
option transport.socket.listen-port 6996
option transport.socket.nodelay on
end-volume
?>

glusterfs.vol
# Generated by Puppet
volume vol-0
type protocol/client
option transport-type tcp
option remote-host ####
option transport.socket.nodelay on
option remote-port 6996
option remote-subvolume iothreads
option username ####
option password ####
end-volume
... # 1 per apache node + 1 per nginx node
volume vol-3
type protocol/client
option transport-type tcp
option remote-host ####
option transport.socket.nodelay on
option remote-port 6996
option remote-subvolume iothreads
option username ####
option password ####
end-volume
volume mirror

-0
type cluster/replicate
subvolumes vol-0 vol-1 vol-2 vol-3
option read-subvolume vol-0
end-volume
volume writebehind
type performance

/write-behind
option cache-size 4MB
# option flush-behind on # olecam: increasing the performance of handling lots of small files
subvolumes mirror-0
end-volume
volume iothreads
type performance

/io-threads
option thread-count 16 # default is 16
subvolumes writebehind
end-volume
volume iocache
type performance

/io-cache
option cache-size 412MB
option cache-timeout 30
subvolumes iothreads
end-volume
volume statprefetch
type performance

/stat-prefetch
subvolumes iocache
end-volume
?>

http://evolvingweb.ca/fr/story/drupal-cloud

NginX with wordpress

> January 10th, 2012 ---

http://kbeezie.com/view/apache-to-nginx/

Rsync setup & backup on CentOS

> September 10th, 2011 ---
1.install rsync on dest
yum install rsync
2.create /etc/rsyncd.conf and /etc/rsyncd.scrt
## sample rsyncd.conf ##
motd file = /etc/rsyncd.motd
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
[soapiece_backup]
path = /home/soapiece/soapiece_backup
comment = soapiece Rsync server
uid = soapiece
gid = soapiece
read only = no
list = yes
auth users = soapiece
secrets file = /etc/rsyncd.scrt
hosts allow = 123.123.123.123
## end sample rsyncd.conf ##
## sample rsyncd.scrt ##
soapiece:12345
## end sample rsyncd.scrt ##
rsync without entering passwd
from src shell : ssh-keygen -t rsa
copy id_rsa.pub to destination server’s user directory : ~user/.ssh/authorized_keys
from src shell : rsync –verbose  –progress –stats –compress –rsh=/usr/bin/ssh –recursive –times –perms –links –delete src dst_usr@dest_ip:soapiece_backup
put above script in cron directory for regular backup.

css text effects

> June 14th, 2011 ---

http://www.1stwebdesigner.com/css/advanced-css-text-effects-web-typography-tips/

export

> June 9th, 2011 ---

mysqldump -uroot -p aaa–ignore-table=log_url_info –ignore-table=log_visitor_info –ignore-table=log_url –ignore-table=log_visitor –ignore-table=report_event –ignore-table=report_viewed_product_index –ignore-table=sales_order_entity_decimal –ignore-table=sales_order_entity_varchar –ignore-table=sales_flat_quote_item_option –default-character-set=utf8 > aaa.sql

Old solution migration tip

> April 13th, 2011 ---

find ./ -type f | xargs perl -pi -w -e ‘s/HTTP_POST_VARS/_POST/g;’
find ./ -type f | xargs perl -pi -w -e ‘s/HTTP_GET_VARS/_GET/g;’
find ./ -type f | xargs perl -pi -w -e ‘s/HTTP_ENV_VARS/_ENV/g;’
find ./ -type f | xargs perl -pi -w -e ‘s/HTTP_SESSION_VARS/_SESSION/g;’
find ./ -type f | xargs perl -pi -w -e ‘s/HTTP_SERVER_VARS/_SERVER/g;’
find ./ -type f | xargs perl -pi -w -e ‘s/HTTP_POST_FILES/_FILES/g;’
find ./ -type f | xargs perl -pi -w -e ‘s/HTTP_COOKIE_VARS/_COOKIE/g;’

Backup batch script.

> March 14th, 2011 ---

mysqldump.exe -uroot -p wp > “c:\backup\wp_%date:~6,4%%date:~0,2%%date:~3,2%.sql”

alzipcon.exe -a source_dir “c:\backup\backup_%date:~6,4%%date:~0,2%%date:~3,2%.zip”

PHP date time validation

> January 25th, 2011 ---

for my reference

$famm = '08';
$fadd = '31';
$fayy = '11';
$fahour = '23';
$famin = '01';
 
$t_time = "$fayy-$famm-$fadd $fahour:$famin:00".'<br>';
echo $t_time;
 
function isValidDateTime($mydate) 
{ 
	list($date,$time)=explode(" ",$mydate);
    list($yy,$mm,$dd)=explode("-",$date);
	list($hour,$min,$sec)=explode(":",$time);
 
    if (is_numeric((int)$yy) && is_numeric((int)$mm) && is_numeric((int)$dd)) 
    { 
 
		$len_hour	= strlen($hour);
		$len_min	= strlen($min);
 
		if ($len_hour == 1)
		{
			$hour	= '0'.$hour;
		}
		if ($len_min == 1)
		{
			$min	= '0'.$min;
		}
		if((is_numeric((int)$hour) && (int)$hour >= 0 && (int)$hour <= 23)&&
			(is_numeric((int)$min) && (int)$min >= 0 && (int)$min <= 59)&&
			checkdate($mm,$dd,$yy))
		{
			return true;
		}
		else
		{
		return false;
		}
    }
	else
	{
		return false;      
	}
}
 
if(isValidDateTime($t_time))
{
	echo 'validated';
}
else
{
	echo 'not validated';
}

Outlook sent email in inbox

> October 5th, 2010 ---

When you send an email in Outlook, sent messages will be automatically stored in ‘Sent Items’. If you’d like to see the sent message in each inbox folder, just add ‘recent:’ in front of the login name.