Installing a monitored Mongodb, Ruby 1.9, Nginx stack with Passenger on Ubuntu Linux

In the spirit of nosql, today I am going to show you how to install a Rails stack on Ubuntu using Mongodb, Nginx, Passenger, Ruby 1.9 and all nicely monitored using monit, my monitoring tool of choice (why don’t I use god I hear you ask? => monit = easy maintenance and less resource heavy).

We used to use Nginx for all of our apps back in the good ‘ol days of mongrel clustering. Since Phusion Passenger, we like most other development companies, moved straight over to Apache for ease of install and maintenance. However we decided recently that we should look at Nginx again, for its super small memory footprint and low server load, as well as super fast serving. Apache is a beast and on small servers without correct optimisation it can eat up resource at a much quicker rate than Nginx.
We ran some side by side comparables on Nginx vs Apache on a 512 slice and the differences are significant. Anyway… on to the install!

I have put semi-colons after each line so in theory you can just copy entire blocks and just paste them into your terminal and they will execute.

Firstly on a blank system (logged in as root) add your user account

adduser deploy;

Then give this user sudo privileges by editing the sudoers file:

visudo;

Make sure the file is correctly saved as sudoers, not sudoers.tmp then log out and back in as your new deploy user.

Now lets get the base system ready, so firstly:

sudo apt-get update;
sudo apt-get upgrade;
sudo apt-get install build-essential zlib1g-dev libssl-dev libpcre3-dev git-core;

Now to install Ruby 1.9 and Rubygems
Go grab Ruby from here

cd;
wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p376.tar.gz;
tar zxvf ruby-1.9.1-p376.tar.gz;
cd ruby-1.9.1-p376;
./configure; make; sudo make install;

Now install libopenssl-ruby

cd;
cd ruby-1.9.1-p376/ext/openssl;
sudo ruby extconf.rb;
make; sudo make install;

And readline (to avoid the readline errors from the console)

sudo apt-get install libreadline5 libncurses5-dev libreadline5-dev;
cd;
cd ruby-1.9.1-p376/ext/readline;
ruby extconf.rb;
make; sudo make install;

Go and fetch Rubygems from here

cd;
wget http://rubyforge.org/frs/download.php/69365/rubygems-1.3.6.tgz;
tar zxvf rubygems-1.3.6.tgz;
cd rubygems-1.3.6;
sudo ruby setup.rb;

Check everything is running as expected:

ruby --version; gem --version;

And you output should show something like this:

ruby 1.9.1p376 (2009-12-07 revision 26041) [i686-linux]
1.3.6

Now to install nginx and passenger:
Grab the latest nginx from here

cd;
wget http://nginx.org/download/nginx-0.7.65.tar.gz;
tar zxvf nginx-0.7.65.tar.gz;

Before you install this, grab passenger and it will install nginx for you:

sudo gem update;
sudo gem install passenger --no-ri --no-rdoc;
sudo passenger-install-nginx-module;

When passenger install loads, select option 2 (advanced) as option one uses an older version of nginx than we just downloaded.
The directory where nginx source code is located is:

/home/deploy/nginx-0.7.65

Make sure you specify what user to run as, in the add extra arguments section add the following:

--user=nginx --group=nginx

And just go with the defaults for everything else. Nginx gets installed in /opt/nginx
Now add the nginx user:

sudo adduser --system --no-create-home --disabled-login --disabled-password --group nginx;

Now install the startup script from linode to get Nginx started:

cd;
wget http://library.linode.com/web-servers/nginx/installation/reference/init-deb.sh;
sudo mv init-deb.sh /etc/init.d/nginx;
sudo chmod +x /etc/init.d/nginx;
sudo /usr/sbin/update-rc.d -f nginx defaults;

Now Nginx is installed with passenger support, all we have left to install is Mongodb and monit.
Starting with mongodb, grab the source from here, make sure you get the correct version for your system architecture as the 32 bit has limitations so if you can install the 64 bit, do!
On the system I am installing it is 32 bit:

wget http://downloads.mongodb.org/linux/mongodb-linux-i686-1.4.1.tgz;
tar zxvf mongodb-linux-i686-1.4.1.tgz;
sudo mv mongodb-linux-i686-1.4.1 /opt/mongodb;

Now create the data directory for mongo (the following instructions have been taken originally from the tutorials at library.linode.com)

sudo mkdir -p /data/db/mongodb;
sudo touch /data/db/mongodb.log;

And create the basic control scripts:

sudo mkdir /opt/bin/;
sudo mkdir /opt/config/;

Copy and paste the following into /opt/bin/mongodb-start:

#!/bin/sh
/opt/mongodb/bin/mongod --config /opt/config/mongodb \
## --upgrade \ ##runs a database upgrade option if needed \

Copy and paste the following into /opt/bin/mongodb-stop:

#!/bin/bash

pid=`ps -o pid,command ax | grep mongod | awk '!/awk/ && !/grep/ {print $1}'`;
if [ "${pid}" != "" ]; then
    kill -2 ${pid};
fi

Copy and paste the following into /opt/config/mongodb:

# Configuration Options for MongoDB
#
# For More Information, Consider:
# - Configuration Parameters: http://www.mongodb.org/display/DOCS/Command+Line+Parameters
# - File Based Configuration: http://www.mongodb.org/display/DOCS/File+Based+Configuration

dbpath = /data/db/mongodb
logpath = /data/db/mongodb.log
logappend = true

bind_ip = 127.0.0.1
port = 27017
fork = true

auth = true
# noauth = true

And make sure the files are executable:

sudo chmod +x /opt/bin/mongodb-start;
sudo chmod +x /opt/bin/mongodb-stop

Now grab the init script from linode:

cd;
wget http://library.linode.com/databases/mongodb/reference/init-deb.sh;
sudo mv init-deb.sh /etc/init.d/mongodb;
sudo chmod +x /etc/init.d/mongodb;
sudo /usr/sbin/update-rc.d -f mongodb defaults;

Add a mongo user and make sure they own the right files:

sudo adduser --system --no-create-home --disabled-login --disabled-password --group mongodb;
sudo chown mongodb:mongodb -R /data;

Ok now to install monit:

sudo apt-get install monit;
sudo mkdir /etc/monit.d;

Now to configure everything!!!
Let start with nginx:

sudo mkdir /opt/nginx/vhosts;

I have created a optimised nginx config file available here. Grab this and copy the contents into /opt/nginx/conf/nginx.conf
The nginx conf assumes that your declare your servers in /opt/nginx/vhosts. If you have issues with passenger make sure the two lines regarding Passenger point to the correct Ruby and Passenger.
Now create your vitualhosts. For the purpose of this article I am going to create one generic one. You can grab this from the gist here and then put it inside the vhosts directory.

Thats Nginx done. Now to sort out monit.
First edit the /etc/default/monit file and make sure startup is set to 1, so it starts on boot.
Now create the monit.d directory:

sudo mkdir /etc/monit.d;

And then edit the /etc/monit/monitrc file. You can grab a template for this from here.
I have created one file for everthing in the /etc/monit.d directory. Grab it from here and then make sure it is executable:

cd /etc/monit.d;
sudo vi the_file_name;
sudo chmod +x the_file_name;

It doesn’t matter what the file is called. Monit will run any file located in the /etc/monit.d directory as we specified that in the monitrc file earlier.
Now start monit!

sudo /etc/init.d/monit start;
sudo monit;
sudo monit start all;
sudo monit status;

And that’s pretty much it! your server is set up with monitoring, nginx, mongodb and ruby 1.9. All you need to do now is set up your deployment strategy.

2 Comments

RSS feed for comments on this post. TrackBack URL

  1. jon Doh — April 23, 2010

    This is great! Thank you so much!!

  2. Travis — June 19, 2010

    Great article. I only needed the MongoDB section, but it helped me out a LOT!

    Thanks!

Leave a comment

Preview: