Nginx for Drupal and for Redis

Recently, I compiled nginx on CentOS 6 for a Drupal 7 installation and for a Redis installation. So, I thought that I would share my steps.

Whenever I compile nginx, I always use the nginx_syslog_patch to enable syslog logging. The only module that is required for Drupal 7 is nginx-upload-progress-module. Here is my configuration for Drupal 7.

First, I added two repositories to get the latest PHP binaries.
rpm -Uhv epel-release-6-8.noarch.rpm
rpm -Uhv remi-release-6.rpm
cd /etc/yum.repos.d/
Enable the remi repository.

yum install git vim openssl php php-fpm php-common php-pear php-pdo php-mysql php-gd php-mbstring php-mcryp mysql gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel make patch readline-devel pcre-devel openssl-devel

Second, get the modules:
git clone
git clone

Download the latest stable release of the nginx source code.
tar -zxvf nginx-1.2.7.tar.gz
cd nginx-1.2.7
patch -p1 < /root/nginx_syslog_patch/syslog_1.2.7.patch After nginx has been patch, you can compile and install. ./configure --add-module=/root/nginx_syslog_patch --add-module=/root/nginx-upload-progress-module --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/ --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-cc-opt='-O2 -g' make; make install Next, you can get the latest stable release of drupal: wget You will need to configure php-fpm and nginx. I recommend starting with the following configuration bundle. This will enable you to get up and running with drupal in a short period of time. I also decided to configure nginx for connecting to Redis. For me the best module for connected to Redis is lua-resty-redis. I recommend it. Download and compile it. OpenResty is nginx with a bunch of nginx modules bundled in. After compiling openresty, you will have an nginx binary with many nice lua modules installed. Below is my openresty configuration. wget tar -xzvf ngx_openresty- cd ngx_openresty- ./configure --add-module=/root/nginx_syslog_patch --add-module=/root/nginx-upload-progress-module --without-lua_resty_memcached --without-lua_resty_mysql --with-luajit --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/ --lock-path=/var/run/nginx.lock --user=apache --group=apache --with-http_realip_module --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --without-http_memcached_module --without-http_auth_basic_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-cc-opt='-O2 -g' Some good resources for nginx and lua are as follows:

Zend Framework 1.12.1 includes protection from cross-site request fogery

Recently, I upgraded from ZF 1.11.9 to 1.12.1, and I discovered that requests from a friendly MS IIS web server were not working. I am using ZF as an API backend and MS IIS as a friendly frontend. The problem was that ZF refused to honor the REDIRECT_URL and overrode REDIRECT_URL with HTTP_X_ORIGINAL_URL. The simple fix was to place the following code in the ZF bootstrap.


Red Hat reported a problem with XSS flaws (see, and the problem was fixed in ZF 2 and ZF 1. However, it created a problem for me.

Kernel tuning for the TCP stack

Below are some kernel tweaks that I use for CentOS 6.2 with a 10 GB NIC.

#Lower syn retry rates, default is 5
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 3

# Tune IPv6
net.ipv6.conf.default.router_solicitations = 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1

# Increase TCP max buffer size setable using setsockopt()
# default 4096 87380 4194304
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608

# Increase Linux auto tuning TCP buffer limits
# min, default, and max number of bytes to use
# set max to at least 4MB, or higher if you use very high Bandwidth-delay product (BDP) paths
# Tcp Windows etc
# default 131071
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
# default 124928
net.core.rmem_default = 524287
net.core.wmem_default = 524287

# default net.core.netdev_max_backlog = 1000, set to 30000 for 10Gbit NICs
net.core.netdev_max_backlog = 32768
# default net.core.somaxconn = 128
net.core.somaxconn = 4096

# You might also try the following:
# default net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_max_syn_backlog = 4096

# metrics slows us down :)
net.ipv4.tcp_no_metrics_save = 1

# default net.ipv4.tcp_no_metrics_save = "32768 61000"
net.ipv4.ip_local_port_range = 1025 65535

# default tcp_fin_timeout = 60
net.ipv4.tcp_fin_timeout = 30

# default net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_intvl = 30

# default net.ipv4.tcp_max_tw_buckets = 180000
net.ipv4.tcp_max_tw_buckets = 1440000

# default net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_time = 400

# default net.ipv4.tcp_keepalive_probe = 9
net.ipv4.tcp_keepalive_probes = 5

# default vm.swappiness = 60
vm.swappiness = 20

# ipcs -l
# default max seg size (kbytes) = 32768
kernel.shmmax = 500000000
# default max total shared memory (kbytes) = 8388608
kernel.shmall = 4000000000
# default max queues system wide = 1024
kernel.msgmni = 2048

net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.conf.all.arp_filter = 1
net.core.netdev_max_backlog = 10000

Also set your per user limits higher in /etc/security/limits.conf:
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072

How to use Pageant and Putty from Windows

Here is a terse HowTo for using putty to ssh into a remote server without using a password.

1. Download Putty installer from the Putty download page. Make sure to grab the windows “Installer”.
2. Install Putty
3. Start PuttyGen from Start -> Putty-> PuttyGen
4. Generate a new key and save it as a .ppk file without a passphrase
5. Use Putty to login to the server you want to connect to
append the public key text from PuttyGen to the text of ~/.ssh/authorized_keys Tip: Copy and paste from the PuttyGen console.
6. Create a shortcut to your .ppk file from Start -> Startup.
7. Select the .ppk shortcut from the Startup menu to start Pageant (this will happen automatically at every startup).
8. See the Pageant icon in the system tray? Right-click it and select “New session”
9. Enter username@hostname in the “Host name” field.
You will now log in automatically.

If your key is not accepted, check your file permissions. SSH is very sensitive directory and file permissions.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Did you get caught by the Leap-second bug?

I happened to be one of the many thousands of systems engineers that got a call at 9:00 p.m. on Saturday, June 30. All of our linux servers with Java applications were under heavy load. Restarting the Java applications did nothing to reduce the system load. After several hours of troubleshooting, we finally decided to reboot the server. Much to my surprise, this fixed the problem.

Some have reported that this was not a Java releated problem; rather, it was a linux problem. See:

Well, linux servers with Apache, MySQL, erlang, python, PHP, C or C++ applications did not have any problems. It was only our Java applications that had problems (e.g., Neo4J, Hbase, Kafka and so on). The following is what I discovered in my troubleshooting.

Java stopped closing threads efficiently, and threads remained open in a “wait” or a “sleep” state for a long time. As a result, Java was using the maximum amount of memory allowed, and garbage collection was not working efficiently. All of our java applications were affected. None of our other applications were effected.

Java applications were the culprit for loading the systems. I agree that the only thing that fixed the problem was resetting the Linux clock (or timer). So, the problem was certainly related to the way Linux updated its clocks during the leap second. However, Oracle needs to step up and take some responsibility. The problem may have started with the Linux clock, but the result was that Java freaked out.

I should have entitled this blog entry as: JAVA Is Culprit in Leap-second Lapses.

Installing ZeroMQ with node.js

Recently, I installed zeromq with node.js and zeromq.node. I had some difficulties, so I thought that I would generate a brief how to.

ZeroMQ installed without much difficulty. On Ubuntu, install the following prerequisite.
apt-get install uuid-dev
On CentOS, install:
yum install libuuid-devel uuid-devel

Then, unpack the tarball and execute: configure, make
As the super user, execute: make install
This will install ZeroMQ in /usr/local/bin

Download and install the latest stable version of node.js. Just unpack the tarball and execute: configure, make
As the super user, execute: make install

The node.js library for 0mq is zeromq.node, and it does not work with the latest development branch of node.js. Rather, you need it install a stable branch of node.js.

Before you install zeromq.node do the following.
1. Make sure that /usr/local/bin is in your path, since there is where node lives.
2. Create the following file: /etc/
The contents of the above file is ‘/usr/local/lib’.
3. Execute the command ‘ldconfig’.
4. export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
5. npm install zmq

If you install zeromq.node (now called ‘zmq’) globally as the super user (with ‘npm install -g zmq’), node.js will likely not be able to find it (in /usr/local/lib/node_modules). So, install it locally as above in your $HOME/node_modules directory.

Now, you should have a working version of zmq with node.js. You can test your installation using the example scripts (e.g., producer.js) on Justin’s github:

Resizing your root file system on Ubuntu with the logical volume manager (LVM)

I recently add some disk space to my root file system on a live, mounted file system using Ubuntu 10.10. I was using a virtual machine, so I changed the size of my disk drive in the virtual machine manager. Then, I logged into Ubuntu as root and executed the following commands.

Partitioned the new drive space with fdisk.
fdisk /dev/hda
In fdisk, “n” (new partition), “p” (primary), “3” (partition number), selected all remaining space on the drive, “t” change the type of partition to “8e” (LVM Volumn), “w” write the changes. I created a new partition on /dev/hda3.

  • partprobe
  • pvcreate /dev/hda3
  • vgextend POC-Ubuntu00 /dev/hda3
  • lvextend /dev/POC-Ubuntu00/root /dev/hda3
  • resize2fs /dev/POC-Ubuntu00/root
  • The volume group is “POC-Ubuntu00”. The logical volume name is “/dev/POC-Ubuntu00/root”.

    Some useful commands: pvdisplay, vgdisplay, lvdisplay.


MongoDB versus Riak Datastore: Some Benchmarks

I was doing some google searches, and I found some benchmarks of MongoDB and Riak.

Mr. Howe benchmarked MongoDB. He was able to get 1,750 GET requests per second from Mongo, when the keys could be stored in memory.

In contrast, the folks at Joyeur were able to get 6,650 GET requests per second on a five-node Riak cluster and 13,700 GET requests per second on a 10-node cluster. These are “highly optimized” Riak clusters, using the “protocol buffers” interface.

In reality, most people do not run “highly optimized” Riak clusters with “protocol buffers”; rather, they run non-optimized Riak clusters over HTTP. I did a quick and dirty informal test of my Riak cluster (Erlang: R13B04, Riak: 0.14.2). I have a three node cluster, and I was testing from a remote server over an internal network, using node.js and riak-js client. I have about 200,000 records in Riak, which is well within the memory requirements of the cluster. In my informal tests, I got about 250 GET requests per second.

One interesting thing to note is that Basho, the company that supports Riak, admits that MongoDB is “more peformant.” The entire quote: “Mongo is more performant because it uses memory-mapped files. The tradeoff is that it fsyncs (flushes in-memory data to disk) only every 60 seconds by default, so you run the risk of losing data if your MongoDB server goes down. The solution for increasing durability in MongoDB is to replicate.” See

The advantage of Riak over Mongo is that Riak automatically replicates and rebalances.

The advantage of MongoDB over Riak is that Mongo supports secondary indexes and a more robust query language.

Both Riak and MongoDB support MapReduce via JavaScript, and both use the SpiderMonkey JavaScript engine. However, Riak’s MapReduce framework is more powerful than MongoDB’s framework because Riak allows you to run MapReduce jobs on a filtered set of keys. By contrast, in Mongo, you have to run MapReduce jobs across an entire database.

Upgrading the pear installer with pear

I recently tried to install the latest version of PHPUnit, and I ran into a bit of trouble. When I installed pear on SLE 10 (zypper install php5-pear), the installer version was too old to download and install PHPUnit. So, I had to upgrade the pear installer to the latest version before I could install PHPUnit. To do this, simply run ‘pear upgrade pear’ from the command line (or in a shell). After you do that, PHPUnit should install without problems.

To install PHPUnit will all dependencies, execute the following from the command line (or in a shell).

pear channel-discover
pear channel-discover
pear channel-discover
pear install --alldeps phpunit/PHPUnit