Munin Graphs for Phusion Passenger (a.k.a. mod_rails)

words by Brian Racer

The goal of this article is to get fairly nice looking graphs of Phusion Passenger’s performance and memory metrics:


This specific setup focuses on CentOS (on cPanel none the less) – but instructions should apply for most linux distros. It assumes you already have Passenger and Munin successfully setup. See my previous article on getting Phusion Passenger setup if you have not already.

First we need to allow the munin user sudo privileges for a few passenger related commands:

$ sudo /usr/sbin/visudo
 
# Add the following line to the file
munin ALL=(ALL) NOPASSWD:/usr/bin/passenger-status, /usr/bin/passenger-memory-stats
 
# Depending on your setup, you may also have to comment out the following line:
Defaults requiretty

If you see the error sorry, you must have a tty to run sudo in /var/log/munin/munin-node.log, comment out the final line shown above.

The following two files will glean some performance and memory statistics.

Passenger Status:

sudo vi /usr/share/munin/plugins/passenger_status
#!/usr/bin/env ruby
 
def output_config
  puts <<-END
graph_category App
graph_title passenger status
graph_vlabel count
 
sessions.label sessions
max.label max processes
running.label running processes
active.label active processes
END
  exit 0
end
 
def output_values
  status = `sudo /usr/bin/passenger-status`
  unless $?.success?
    $stderr.puts "failed executing passenger-status"
    exit 1
  end
  status =~ /max\s+=\s+(\d+)/
  puts "max.value #{$1}"
 
  status =~ /count\s+=\s+(\d+)/
  puts "running.value #{$1}"
 
  status =~ /active\s+=\s+(\d+)/
  puts "active.value #{$1}"
 
  total_sessions = 0
  status.scan(/Sessions: (\d+)/).flatten.each { |count| total_sessions += count.to_i }
  puts "sessions.value #{total_sessions}"
end
 
if ARGV[0] == "config"
  output_config
else
  output_values
end

Memory Stats:

sudo vi /usr/share/munin/plugins/passenger_memory_status
#!/usr/bin/env ruby
# put in /etc/munin/plugins and restart munin-node
# by Dan Manges, http://www.dcmanges.com/blog/rails-application-visualization-with-munin
# NOTE: you might need to add munin to allow passwordless sudo for passenger-memory-stats
 
def output_config
  puts <<-END
graph_category App
graph_title Passenger memory stats
graph_vlabel count
 
memory.label memory
END
  exit 0
end
 
def output_values
  status = `sudo /usr/bin/passenger-memory-stats | tail -1`
  unless $?.success?
    $stderr.puts "failed executing passenger-memory-stats"
    exit 1
  end
  status =~ /(\d+\.\d+)/
  puts "memory.value #{$1}"
end
 
if ARGV[0] == "config"
  output_config
else
  output_values
end

Now we will link these to the active plugins, and make them executable:

sudo chmod +x /usr/share/munin/plugins/passenger_status
sudo chmod +x /usr/share/munin/plugins/passenger_memory_status
sudo ln -s /usr/share/munin/plugins/passenger_status /etc/munin/plugins/passenger_status
sudo ln -s /usr/share/munin/plugins/passenger_memory_status /etc/munin/plugins/passenger_memory_status

Last thing we need to do is make sure those scripts run as the munin user:

sudo vi /etc/munin/plugin-conf.d/munin-node
[passenger_*]
user munin
command ruby %c

Restart the munin node, and wait and you should see the graphs start to propagate.

sudo /etc/init.d/munin-node restart

For even more detailed performance analytics, checkout NewRelic monitoring. And thanks to Dan Mange for the munin scripts.


Clean Webalizer Referrer Stats in cPanel

words by Brian Racer

I find it useful to override some of cPanel’s default webalizer configurations. There can be a lot of misleading or unnecessary data when you don’t ignore traffic that is being referred to from your own site.

Create the following file:

vi /home/username/tmp/webalizer/webalizer.conf
HideSite *example.com
HideSite localhost
HideReferrer example.com/
MangleAgents 4
 
TopSites        10
TopKSites       10
TopURLs         10
TopKURLs        50
TopReferrers    250
TopAgents       15
TopCountries    10
TopEntry        10
TopExit         10
TopSearch       20
TopUsers        20
 
# Usually you want to hide these
HideURL         *.gif
HideURL         *.GIF
HideURL         *.jpg
HideURL         *.JPG
HideURL         *.png
HideURL         *.PNG
HideURL         *.bmp
HideURL         *.BMP

Replace example.com with the domain you are working on. The next time webalizer runs it will not be clogged with useless referrers generated by your site. To force webalizer to run(in a cPanel environment), execute:

/scripts/runweblogs username

Install Phusion Passenger (a.k.a. mod_rails) on cPanel Server

words by Brian Racer

Although cPanel has built in support for running Ruby or Rails apps, it uses Mongrel as the server and doesn’t allow more than one instance per user. That makes it pretty useless for any application that gets even a moderate amount of traffic. Instead we can install Phusion Passenger (a.k.a mod_rails), which in my opinion is a much nicer solution anyway.

First we need to make sure Ruby is installed via a cpanel script:

sudo /script/installruby

Now we can install the passenger gem:

sudo gem install passenger

Next, compile the apache2 module

sudo passenger-install-apache2-module

The installer may tell you that the the Apache development headers are needed and will suggest ‘yum install httpd-devel’. Since cPanel compiles it’s own version of apache, yum is configured to ignore that package. That is OK, because the program we need is already installed, we just have to tell Passenger where to find it.

APXS2=/usr/local/apache/bin/apxs PATH=$PATH:/usr/local/apache/bin passenger-install-apache2-module

Everything should go OK this time, and the installer will give you a few lines to add to your apache config file. It’s best practice with cPanel not to put these in your main httpd.conf, but rather the pre_main_global.conf:

vi /usr/local/apache/conf/includes/pre_main_global.conf
 
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-X.X.X/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-X.X.X
PassengerRuby /usr/bin/ruby

Now we need to setup passenger to run on a per virtual host basis. Open up the httpd.conf file and find the virtual host you want to run a Rails app and add this line:

Include "/usr/local/apache/conf/userdata/std/2/username/domain_name/*.conf"

Replace username with the username of the account.

Now we need to create the directory we just specified, and also create a configuration file letting passenger know it should load for this host:

mkdir -p /usr/local/apache/conf/userdata/std/2/username/domain_name/
vi /usr/local/apache/conf/userdata/std/2/username/domain_name/rails.conf
 
RailsBaseURI /

To make sure those files load, run this:

/scripts/ensure_vhost_includes --user=username

We need to make sure cPanel records the changes we have for when it rebuilds those files, so run the following two commands:

/usr/local/cpanel/bin/apache_conf_distiller --update
/usr/local/cpanel/bin/build_apache_conf

We can now restart apache:

/etc/init.d/httpd restart

Since by default the Apache Document Root for each host is /home/username/public_html, you will probably need to symlink that to your applications public directory:

ln -s /home/username/railsapp/public /home/username/public_html

To restart that application, you just need to touch the restart.txt file:

touch /home/username/railsapp/tmp/restart.txt

And there you have it, a working high performance rail application server on cPanel! For more information on tuning the Passenger configuration, read the complete docs.


How to fix Munin’s MySQL Graph on cPanel

words by Brian Racer

We have a few cPanel servers deployed and to visually monitor performance we use the Munin monitoring tool. We were having issues where the MySQL graphs would stop updating. The bug has to do with one of the perl libraries the script uses, which causes the MySQL plugin to have problems location the mysqladmin program.

To fix these, create or edit the following file:

vi /etc/munin/plugin-conf.d/cpanel.conf

It should contain the following:

[mysql*]
user root
group wheel
env.mysqladmin /usr/bin/mysqladmin
env.mysqlopts --defaults-extra-file=/root/.my.cnf

This would load the username and password from root’s mysql config. If that file doesn’t exist you can create it:

sudo vi /root/.my.cnf
[client]
user="root"
pass="secret!password"

Now just restart Munin, wait a a little bit, and the graphs should start populating again!

sudo /etc/init.d/munin-node restart