A Response To Quality

"Doing things the right way is hard, which is why most businesses take the lazy path and settle for mediocrity. People respond to quality, though: they reward it, in no small part because quality is such a rarity in today’s marketplace. Do right by your customers and they’ll do right by you."

Source: Shortchanging Your Business with User-Hostile Platforms

PHP-FPM Plugin Suite For Munin

Since switching from a spawn-fcgi implementation several months ago, I’ve been really pleased with PHP-FPM. Given some of the new statistical features included in newer versions (5.3.2+), I put together a plugin suite for Munin. I am not proficient in Perl so I encourage feedback and suggestions to make these better. This suite contains plugins to measure average process size, total memory usage, connection count, process count and most importantly, pool status.

Before installing, make sure you have the most recent version of PHP-FPM:

[www-data@lenny:/var/www]# php-fpm -v
PHP 5.3.2-1ubuntu4.5ppa5~lucid1 (fpm-fcgi) (built: Sep 22 2010 08:04:01)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH

Now we can get into our plugin directory, clone the plugins from my Git repo and make them executable:

cd /usr/share/munin/plugins
git clone git://github.com/tjstein/php5-fpm-munin-plugins.git
chmod +x PHP5-FPM-Munin-Plugins/phpfpm_*

To enable the plugins, you’ll need to create these symlinks:

ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_average /etc/munin/plugins/phpfpm_average
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_connections /etc/munin/plugins/phpfpm_connections
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_memory /etc/munin/plugins/phpfpm_memory
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_status /etc/munin/plugins/phpfpm_status
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_processes /etc/munin/plugins/phpfpm_processes

Note: For the phpfpm_status and phpfpm_connections plugins, you’ll need to enable the status feature included in newer versions (5.3.2+) of PHP-FPM. Open up the php5-fpm.conf, in /etc/php5/fpm, and uncomment line 186 for the pm.status_path directive:

pm.status_path = /status

Jérôme Loyet from the Nginx forums provided some useful insight on how to get this working with Nginx. You’ll essentially set up the status location directive like this:

location ~ ^/(status|ping)$ {
    include fastcgi_params;
    fastcgi_pass backend;
    fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
    allow stats_collector.localdomain;
    allow watchdog.localdomain;
    deny all;

You’ll need to make sure that from within your box, you can curl /status with # curl http://localhost/status. You should get a response similar to this:

accepted conn: 40163
pool: www
process manager: dynamic
idle processes: 6
active processes: 0
total processes: 6

Once the plugins have been set up, you run any of the plugins manually using the munin-run command line tool:

cd /etc/munin/plugins && munin-run phpfpm_status

The output should look like this:

idle.value 6
active.value 0
total.value 6

Note: The phpfpm_status plugin is particularly useful if you’re using dynamic process management. You can choose static or dynamic in the php5-fpm.conf.

Requirements: libwww-perl

Rails 3.0 with RVM, Nginx and Phusion Passenger

Rails 3.0 is ponies and rainbows! Well, kinda. I've never been into Rails much but 3.0 has brought on some much needed features over previous versions, some of which deserve bullet points:

  • Brand new router with an emphasis on RESTful declarations
  • Unobtrusive JavaScript helpers with drivers for Prototype, jQuery, and more coming (end of inline JS)
  • Explicit dependency management with Bundler

The newest version of Rails came out on August 29 so I decided to jump right in. Since Ruby 1.8.6 and earlier are no longer supported, we'll be using RVM in this article. RVM is a command line tool which allows us to easily install, manage and work with multiple ruby environments from interpreters to sets of gems.

Before we get started, we'll be using a fresh (ve) Server from (mt) Media Temple running Ubuntu 10.04 Lucid Lynx for the install. I should also note that we're not installing a full-featured application -- this is simply a tutorial on how to get the Rails 3.0 test application up and running with Nginx + Passenger.

Prerequisites: You'll need these to get through the entire install process for RVM, Nginx and Phusion Passenger (mod_rails).

aptitude -y install curl git-core build-essential zlib1g-dev libssl-dev \
libreadline5-dev libc6 libpcre3 libssl0.9.8 zlib1g

Now we'll need to do a system-wide install of RVM. For your convenience, the dude that wrote RVM provided a script you can run on most that does all the heavy lifting:

bash < <( curl -L http://bit.ly/rvm-install-system-wide )

Every piece of documentation and website I read on this had this particular part wrong. I've updated the correct path from the documentation for the purposes of this article:

echo "[[ -s '/usr/local/lib/rvm' ]] && source '/usr/local/lib/rvm'" >> ~/.bashrc
source ~/.bashrc

Doing so ensures RVM is loaded as a function (versus as a binary), ensuring commands such as rvm use work as expected. Please note that you can confirm this worked correctly by opening a new shell and running:

type rvm | head -n1

If this was performed correctly, you should see:

rvm is a function

So if that looks good, we can continue installing Ruby:

rvm install 1.9.2

Now sit back and relax. This took about 8 minutes on my system. To make sure that the system uses this version, we can use RVM for this and install the rails and passenger gems:

rvm --default ruby-1.9.2
gem install rails passenger

Now comes the fun part of installing Nginx. This will grab the stable binary, bake in Phusion Passenger and compile it:

rvmsudo passenger-install-nginx-module

You will be presented with two options right from the start. Just choose Option 1 and let passenger download, compile and install Nginx for you. You'll also be prompted to choose a prefix directory. You can leave it as the default, /opt/nginx. When it completes, it should give you some Nginx configuration snippets for your rails apps. Save those as you'll need them later.

Now, you'll want a init script so you can stop/start/restart Nginx. I've provided mine here:

cd /etc/init.d
wget -O nginx http://bit.ly/8XU8Vl
chmod +x nginx
/usr/sbin/update-rc.d -f nginx defaults

We're almost done. Now we can create the test application:

cd /opt/nginx/html
rails new testapp

You'll need to update the Nginx configuration to make sure it's using the right document root now. The file will be located in /opt/nginx/conf/nginx.conf:

sed -i".bak" '47d' /opt/nginx/conf/nginx.conf
sed -i '47 a\
            root   /opt/nginx/html/testapp/public;' /opt/nginx/conf/nginx.conf
/etc/init.d/nginx start

The spacing looks a little weird in that middle sed command for a purpose -- to keep the syntax of the nginx.conf file consistent. Now that we've restarted Nginx, we should see the 'Welcome aboard: You're riding Ruby on Rails!' image:

You're riding Ruby on Rails!

If you're interested in an all-in-one installation, I've put together the steps above into a simple bash script. Enjoy!

Wilco and Intelligentsia Mug

I love Wilco. I also love Coffee. So when the coffee-connoisseurs Intelligentsia teamed up with Chicago-based band, Wilco, to offer an exclusive Wilco/Intelligentsia co-branded mug, an impulse purchase was made.

Wilco & Intelligentsia Mug

If you're interested in purchasing one, head over to the Intelligentsia store.

APC Plugin For Munin

If you're like me, you want to monitor and graph every little piece of your server. Until recently, I've been relying on a simple PHP script to display APC statistics. Although the tool worked well, I wanted to integrate the statistics into Munin, as most all other server properties and system services are monitoring with it. The problem was that finding a suitable APC plugin for Munin proved to be very difficult. Fortunately I stumbled across this German gem (Vielen Dank, dass Sie meine deutsche Freundin!) that met my needs. To set this up on your system, just follow the directions below:

First, let's set up the apcinfo.php file in the document root of your web server and retrieve the file from a private gist:

cd /var/www/html
wget -O apcinfo.php http://goo.gl/Lgfmz

Now, make the file executable:

chmod +x apcinfo.php

The script itself is very simple. It simply ouputs the total cache memory, memory available and memory used:

$mem = apc_sma_info();
$mem_size = $mem['num_seg']*$mem['seg_size'];
$mem_avail= $mem['avail_mem'];
$mem_used = $mem_size-$mem_avail;
$out = array(
    'size: ' . sprintf("%.2f", $mem_size),
    'used: ' . sprintf("%.2f", $mem_used),
    'free: ' . sprintf("%.2f", $mem_avail)

echo implode(' ', $out);

To confirm that the script is working, check out /apcinfo.php on your site. You should see something like the following:

size: 31457200.00 used: 19478104.00 free: 11979096.00

Now, let's set up the Munin plugin that will use that information:

cd /usr/share/munin/plugins
wget -O apc http://goo.gl/gUgkj 
chmod +x apc
ln -s /usr/share/munin/plugins/apc /etc/munin/plugins/apc

What that does is create the apc plugin, makes it executable and then symlinks it to the proper directory. Now, we'll need to make sure Munin loads the new plugin. To do this, we'll edit the /etc/munin/plugin-conf.d/munin-node to add the following:

user root
env.url http://example.com/apcinfo.php

Obviously, you'll want to replace example.com with the host you intend to use. Once the file has been updated and saved, restart Munin:

/etc/init.d/munin-node restart

Once the node is running, it'll take a few minutes for Munin to update so don't worry if you don't see any new graphs right away. One thing to keep in mind is that you will need the LWP::UserAgent Perl module. If you are on a Debian/Ubuntu OS, just run the following to install it:

aptitude install libwww-perl

Now, go check your pretty graphs.