RSS
 

Posts Tagged ‘ruby’

CouchDB Security in Ruby

30 Oct

To get some background on couchDB security read here.

All the code samples below, require the Restclient rubygem. You can install it with the command:

gem install rest-client

And Require it in your code with:

require 'rest_client'

Let’s say your couchDB is in Admin Party mode. To end the admin party and add an admin user:

RestClient.put 'http://127.0.0.1:5984/_config/admins/james', '"ssstepin"',{:content_type => :json}

james is the name of the new admin, and his password is ssstepin. The password needs to be enclosed in double quote,to denote a string in the couchDB configuration.

To authenticate the admin user:

response = RestClient.post 'http://127.0.0.1:5984/_session', 'name=james&password=ssstepin',{:content_type => 'application/x-www-form-urlencoded'}
puts response.cookies
# => {"AuthSession"=>"b2tlOjRFQUJCNzE0OkXtpl9cxR_zbIxvlvW2J60txIwT", "Version"=>"1", "Path"=>"%2F"}

This returns the authentication token for making future requests, on behalf of the authenticated user.

To add a new admin user:

RestClient.put 'http://127.0.0.1:5984/_config/admins/david', '"wuzz234"',{:cookies => {"AuthSession" => "b2tlOjRFQUJCNzE0OkXtpl9cxR_zbIxvlvW2J60txIwT"}}

We added a new admin david with password wuzz234, we made the request on behalf of james (see the AuthSession token, we are using the same token generated for james).

To delete the new admin user:

RestClient.delete 'http://127.0.0.1:5984/_config/admins/david',{:cookies => {"AuthSession" => "b2tlOjRFQUJCNzE0OkXtpl9cxR_zbIxvlvW2J60txIwT"}}

We deleted the admin david, we made the request on behalf of james (see the AuthSession token). If you delete all admins CouchDB will switch back to Admin Party.

To create a non-admin user:

salt = "somerandomstring123"
password = "seenow109"
password_sha = Digest::SHA1.hexdigest(password + salt)
 
user_hash = { :type => "user",
                   :name => "nancy",
                   :password_sha => password_sha,
                   :salt => salt,
                   :roles => []
                  }
 
 
 str = Yajl::Encoder.encode(user_hash)
 
RestClient.put "http://127.0.0.1:5984/_users/org.couchdb.user:nancy", str, {:content_type => :json, :accept => :json}

We created the non-admin user nancy with password seenow109. The above code implements in ruby code the security features explained here. Note that non-admins are authenticated with the same API call as admins.

To create a new database with the authenticated admin user:

RestClient.put 'http://127.0.0.1:5984/contacts', {:content_type => :json},{:cookies => {"AuthSession" => "b2tlOjRFQUJCNzE0OkXtpl9cxR_zbIxvlvW2J60txIwT"}}

We created a new database called contacts. This request was made by the user james, notice the AuthSession token in the request.

To add a security object to the contacts database:

security_hash = { :admins => {"names" => ["nancy"], "roles" => ["admin"]},
                   :readers => {"names" => ["nancy"],"roles"  => ["admin"]}
                  }
security = Yajl::Encoder.encode(security_hash)
 
response = RestClient.put 'http://127.0.0.1:5984/contacts/_security',security,{:cookies => {"AuthSession" => "b2tlOjRFQUJCNzE0OkXtpl9cxR_zbIxvlvW2J60txIwT"}}

The above example uses the yajl-ruby gem to encode the ruby hash to JSON.

To add a new document to the contacts database with the authenticated user session

data = { :name => 'sunny',
         :email => 'sunny@winter.com'
         }
 
 str = Yajl::Encoder.encode(data)
 
 RestClient.put "http://127.0.0.1:5984/contacts/sunny", str, {:cookies => {"AuthSession" => "b2tlOjRFQUJCNzE0OkXtpl9cxR_zbIxvlvW2J60txIwT"}}

We added a document with _id sunny to the contacts database. The above example also uses the yajl-ruby gem for json encoding.

I hope this was helpful. If you find any errors or have suggestions please let me know in the comments.

 
 

Developing Ragios Version 0.5+

13 Apr

I have started testing design ideas for Ragios version 0.5+. Ragios started as a fun way to play with Linux servers and hack the Ruby language. Since then I started using Ragios to monitor web services for my business. Ragios is still very much in alpha stage but its slowly getting somewhere* and I am really enjoying the journey.

Below are some design goals for version 0.5+

Goals

  • Create a plugin architecture, so that all monitors (example HTTP, DNS,process monitors) are added as plugins. This will allow developers to easily write customized plugins. OR easily install plugins written by other developers.
  • Create a simple http server for Ragios that responds to REST requests. This will enable other apps to communicate with Ragios via REST. Example a Rails, Sinatra or javascript app could provide a Web User Interface for Ragios via REST. The datafeed from Ragios could be fed to a webpage, blog, widget or mobile app via REST.
  • Add ability to persist Ragios information and real-time statistics to a database. This will allow service performance monitoring overtime. It will also enable better control of monitors.

 
I have started working on the first goal. In the new design all monitors are plugins. These plugins are simple ruby classes that can monitor URLs, system processes, Mail servers etc.

I hope to keep the same simple syntax for Ragios

    monitoring  =  { :monitor => 'url',
                   :every => '5m',
                   :test => 'video datafeed test',
                   :url => 'http://www.datafeed.com/resources/videos/1',
                   :contact => 'admin@mail.com',
                   :via => 'gmail',
                   :notify_interval => '6h'
 
                  },
                  {:monitor =>'http',
                   :every => '30s',
                   :test => 'Http connection to client A website',
                   :domain => 'www.clientA.com',
                   :contact => 'admin@mysite.com',
                   :via => 'twitter',
                   :notify_interval => '6h'
                  }
 
  Ragios::Monitor.start monitoring

Below is a Gist I created to test design ideas for the new plugin system. I will be updating the Gist as I code in real time. The end result will be the bare bones design for the new system. After I get a workable design I will update the Github Repo here.

 

Installing Ruby 1.9.2 & Rails 3 on Ubuntu with a single command

07 Mar

I wrote a script that installs Ruby 1.9.2 with RubyGems, Rails 3 and sqlite on Ubuntu with a single command. This script makes it very easy to get started developing Rails applications on Ubuntu. Its also an easy way for non-ruby developers to run popular Rails applications.

This is a script I originally wrote, a while ago for Ruby 1.8.7 and Rails 2, I recently realized that most of the traffic coming to my blog were people looking to setup Rails on Ubuntu. So I decided to update the script for Rails 3 and Ruby 1.9.2. So please enjoy.

I remember about 2 years ago, when I got kicked out of a shared hosting account because I was using too much CPU time, I was forced to move my high traffic web service to EC2. I was still new to Linux, it was my first time deploying a Rails app in production, and I was going to go live with thousands of users instantly. It was a nightmarish weekend. That’s why I write scripts like this, to help new users from Windows and OS X get comfortable with the Linux world.  Although Ubuntu 10 is much easier than 8.10, and Ruby 1.9.2 is a big improvement, Rails 3 with bundler is also a big relief, this is a script I wish I had 2 years ago while deploying my first Rails app.

Assumptions Made by the script

The script assumes you don’t have an older version of Ruby like (1.8.7) installed on the system. If you already have an older version of Ruby installed, use RVM instead of this script. To check if you have an older version of Ruby installed type

ruby -v

Installing and setting up Rails with a single command

Step 1: Install Git if you don’t already have it

 sudo apt-get install git-core

Step 2: Download the script from Github

 git clone git://github.com/obi-a/speedtrain.git

Step 3: Change to the speedtrain directory (the script is called speedtrain)

 cd speedtrain

Step 4. Make the script executable

 chmod +x speedtrain

Step 5. Run the script

 ./speedtrain

This will install Ruby 1.9.2,RubyGems, Rails 3 and Sqlite. It will create a folder in your $HOME directory for your Apps called rails_apps. It will also create a sample Rails App called testapp.

To run the sample Rails app. Type…

 cd $HOME/rails_apps/testapp
 rails server

To view the app, open a browser and type http://localhost:3000/

To create a new Rails app. Type..

 cd $HOME/rails_apps
 rails new myapp

Who should use this script

  • Rubists from MS Windows and OS X getting into Ruby/Rails/Linux
  • Non-Rubists that need to run Rails apps on Ubuntu
  • Newcomers to the Ruby/Linux World
  • Rubists that only need Ruby 1.9.2

Related Posts:

Ubuntu, Ruby, RVM, Rails and You

Source code for the script: https://github.com/obi-a/speedtrain/blob/master/speedtrain

 
 

Installing Ruby 1.9.2 on FreeBSD

06 Jan

I’m new to FreeBSD and I’m really loving it. As a Ruby developer here’s how to get started with FreeBSD.

Some things you might need, before you install Ruby
FreeBSD comes with csh by default, which is fun but its a bit cryptic. You might want to simply use the bash shell. The following installations may take a long time to complete because we are building everything from source.

To Build and install Bash

# whereis bash
bash: /usr/ports/shells/bash
 
# cd /usr/ports/shells/bash
# make install clean

To use bash, type:

# /usr/local/bin/bash

To make bash the default shell:

# chsh -s /usr/local/bin/bash {username}
# chsh -s /usr/local/bin/bash obi

To Build and Install wget

# whereis wget
wget: /usr/ports/ftp/wget 
 
# cd /usr/ports/ftp/wget
# make install clean

To Build and install python
We will need Python to build Git later.

# whereis python
python: /usr/ports/lang/python
 
# cd /usr/ports/lang/python
# make install clean

To Build and install Git
Git source mirror.

# wget http://www.kernel.org/pub/software/scm/git/git-1.7.3.4.tar.gz
# tar xzf git-1.7.3.4.tar.gz
# cd git-1.7.3.4
# ./configure
# gmake
# gmake install
 
#git version
git version 1.7.3.4

To Build and install Ruby 1.9.2

# wget ftp://ftp.ruby-lang.org//pub/ruby/1.9/ruby-1.9.2-p136.tar.gz
# tar xzvf ruby-1.9.2-p136.tar.gz
# cd ruby-1.9.2-p136
# ./configure
# make install
 
# ruby -v
ruby 1.9.2p136 (2010-12-25 revision 30365) [i386-freebsd8.1]
 
# gem -v
1.3.7
 
# irb -v
irb 0.9.6(09/06/30)

We are all set. We now have the same Ruby environment on BSD as we use on Linux. I used this setup to test Ragios on FreeBSD. Bundler installed all the required gems with no problems.

If I missed something something in this write-up, please let me know in the comments.
Happy New Year!

 
 

Moving an old Rails 2 App to a New Server Using Bundler

04 Dec

I’ve had this Rails 2.3.2 app running on an Amazon EC2 small instance since March 2009. The app does some back-end processing for the media player software I created for SecondLife. The App stack is nginx, Rails 2.3.2, and some Mongrels. I decided to switch to a micro instance. This will cut my monthly bill from $60 to around $15. The 613MB RAM available on the micro-instance should be more than enough for my app. Amazon also just announced free basic resource monitoring for EC2 instances which means i can easily monitor resource usage to be sure my app isn’t running out of resources.

Packaging Rails Apps with Bundler
I first discovered Bundler while looking for an easy way to deploy Ragios. Ragios now uses Bundler for dependency management. With bundler I can just package my Rails app with all its dependencies (gems) and copy it to a new system. Bundler will install the right version of all the rubygems required for my app to run on the new system.

This is how I used it;

On the old Server
First install the Bundler Rubygem

sudo gem install bundler

Change directory to the root of your rails app

cd myapp

Create a GemFile for your rails app

bundle init

The Gemfile is created in the root directory of your rails app.
Edit the Gemfile and add the gems used by your app.

Example,

gem "rails"

or

gem "rails" , "2.3.2"

Include version number if you want bundler to use a specific version of the gem.

In my case, I wanted every gem on the new server to be exactly the same version as the gems on the old server. So I added version numbers for each gem.

If you want to list all the gems on your system to see their version number, run the ‘gem list’ command;

gem list

Below is a copy of my Gemfile:

source "http://rubygems.org"
 
gem "rails", "2.3.2"
gem "hpricot","0.8.1"
gem "simple-rss","1.2"
gem "rake","0.8.7"
gem "mongrel","1.1.5"
gem "mongrel_cluster","1.0.5"

You don’t need to add every gem on gem list to your Gemfile. You just need the gems you installed and required on your app. Bundler will detect the rest and install all dependencies. Example activesupport, actionmailer etc. will be installed by Bundler for the Rails gem.

Next ;

sudo bundle install

With this command, bundler will download and install all the listed gems and their dependencies. If you already have the gems installed on your system, bundler will use the one you already have. Below is the output from running bundle install with my Gemfile;

Fetching source index for http://rubygems.org/
Using rake (0.8.7) 
Using activesupport (2.3.2) 
Using actionpack (2.3.2) 
Using actionmailer (2.3.2) 
Using activerecord (2.3.2) 
Using activeresource (2.3.2) 
Using cgi_multipart_eof_fix (2.5.0) 
Using daemons (1.1.0) 
Using fastthread (1.0.7) 
Using gem_plugin (0.2.3) 
Using hpricot (0.8.1) 
Using mongrel (1.1.5) 
Using mongrel_cluster (1.0.5) 
Using rails (2.3.2) 
Using simple-rss (1.2) 
Using bundler (1.0.7) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.

When you run bundle install, it will creates a file Gemfile.lock, this file contains a map of all your gems and their dependencies. Bundler will use this file to install gems on the new server.

Now copy the entire directory of your rails app to the new server. Make sure you have Gemfile and Gemfile.lock in the root directory of your Rails app when you copy it to the new server.

On the new server
With your Rails app now copied to this server,

Install bundler

sudo gem install bundler

Change directory to the root of your rails app;

cd myapp

Run bundler to download and install the gems required for your rails app to run on this server

bundle install

After this, your Rails app is ready to run on the new server. You can test it with WEBrick.

I then installed Apache and Phusion Passenger.

Ruby has come a long way, it took only a few minutes to move the app from the old server and setup it up on a new server.

You can see I also switched the app from nginx/mongrels to Apache/Passenger.

There are other ways to use bundler with Rails 2.3, since this is the only Rails app I plan to run on this server, I simply needed Bundler to install the right version of all my gems globally in the system for MRI to use.

Hope this was helpful.

More info on Bundler here.

 
 

St. Ruby: Adding a Daemon and a Scheduler

09 Oct

Its time to add a real scheduler to the St. Ruby (Ragios) system. We need to be able to set time intervals for each system test performed by Ragios. The system admin sets the time interval for ragios to perform each test.

The Scheduler
We need to add a time_interval attribute to the SystemMonitor Class. Ragios will run the test_command method every time_interval.

#base class that defines the behavior of all system monitors
class SystemMonitor
...
    attr_reader :time_interval
 
   #defines the tests to run on a system
   def test_command
   end
...
end

Time interval could be in seconds, minutes, hours or combined.
Example

@time_interval = '3m'  #means the test will run every 3 minutes
@time_interval = '4h'  #every 4 hours
@time_interval = '30s' #every 30 seconds
@time_interval = '6h30m' #every 6 hours 30minutes

We need a scheduler to execute the tests every Time Interval. We will use the rufus-scheduler rubygem for this.

Installing the gem

sudo gem install rufus-scheduler --source http://gemcutter.org

Sample code using the scheduler

require 'rubygems'
require 'rufus/scheduler'
 
scheduler = Rufus::Scheduler.start_new
 
scheduler.every '40m' do
    puts 'download news feed'
end
 
scheduler.every '3h' do
    puts 'ping remote server'
end

Now lets implement a scheduler for Ragios.

#defines how services will be monitored
class Service < SystemMonitor
    def initialize
     super
    end
end
 
class TestServiceA < Service
   def initialize
      @test_description  = "Test Service A"
      @time_interval = '8h'
      super
   end
 
   def test_command
      #test servcie A
      #return TRUE if test passed; FALSE if failed;
   end
 
  def failed
  end
end #end of TestServiceA
 
class TestServiceB < Service
   def initialize
      @test_description  = "Test Service B"
      @time_interval = '45m'
      super
   end
 
  def test_command
      #test servcie B
      #return TRUE if test passed; FALSE if failed;
   end
 
  def failed
  end
end #end of TestServiceB
 
class TestServiceC < Service
   def initialize
      @test_description  = "Test Service C"
      @time_interval = '20s'
      super
   end
 
  def test_command
      #test servcie C
      #return TRUE if test passed; FALSE if failed;
   end
 
  def failed
  end
end #end of TestServiceC
 
jobs = [ TestServiceA.new, TestServiceB.new, TestServiceC.new]
 
puts "Welcome to Ragios"
puts "Initializing"
 
...
 
#schedule all the jobs to execute test_command() at every time_interval
scheduler = Rufus::Scheduler.start_new
jobs.each do |job|
    scheduler.every job.time_interval do
     begin
       if job.test_command
           puts job.test_description + "   [PASSED]" + " Created on: "+ Time.now.to_s
       else
           puts job.test_description +   "   [FAILED]" + " Created on: "+ Time.now.to_s
           job.failed
       end
       #catch all exceptions
      rescue Exception
          puts "ERROR: " +  $!  + " Created on: "+ Time.now.to_s
          job.error_handler
      end
   end #end of scheduler
end
 
#trap Ctrl-C to exit gracefully
puts "PRESS CTRL-C to QUIT"
  loop do
  trap("INT") { puts "\nExiting"; exit; }
    sleep(3)
  end

In the sample code, we have 3 tests running at different time intervals, we set the Tests to run on the Ragios system here;

jobs = [ TestServiceA.new, TestServiceB.new, TestServiceC.new]

We use the rufus-scheduler to set each test to run it’s test_command at its own specified time interval.
When a test fails it calls the failed method for that test.

scheduler = Rufus::Scheduler.start_new
jobs.each do |job|
    scheduler.every job.time_interval do
     begin
       if job.test_command
           puts job.test_description + "   [PASSED]" + " Created on: "+ Time.now.to_s
       else
           puts job.test_description +   "   [FAILED]" + " Created on: "+ Time.now.to_s
           job.failed
       end
       #catch all exceptions
      rescue Exception
          puts "ERROR: " +  $!  + " Created on: "+ Time.now.to_s
          job.error_handler
      end
   end #end of scheduler
end

We also added an Exception handler, in case the test_command or failed method throws an exception. This is useful because it means there maybe a bug in the ruby code for the test or something wrong with the test. We want to alert the system admin about the Exception. I added a new method called error_handler to the SystemMonitor Class (the superclass of all tests). This will help system admins and developers fix bugs in the test’s ruby code. $! is a ruby global variable that holds the details of the last Exception that occurred in the system.

From the view of a system admin Ragios is running tests but the tests are referred to as jobs in the code. The reason for this is that under the hood, Ragios views the tests as jobs. As far as Ragios is concerned its just running a bunch of jobs at their scheduled time intervals. This is a layer of abstraction. Ragios doesn’t know what a test is. It views them as jobs while a system admin views it as tests. This is why I call it tests in the description while its called jobs in the code. (Eventually we will hide all this stuff inside an object).

Finally, we want Ragios to run until its signaled to quit by a CTRL-C from the computer user. We will trap CTRL-C so that Ragios can exit gracefully.

puts "PRESS CTRL-C to QUIT"
  loop do
  trap("INT") { puts "\nExiting"; exit; }
    sleep(3)
  end

Real World Example
Lets try a real-world test. We will use the TestWebpageForHttp200 that tests a website to check if the home page is loading. It sends a http request to the webpage and returns TRUE (test passed) when it gets a http 200 response. It returns FALSE (test failed) when it gets a different http response code from 200.

class TestWebpageForHttp200 < Service
 
   attr_reader :test_url
 
   def initialize
        @contact = "obi@mail.com"
        @describe_test_result = "HTTP Request to " + @test_url
        super
        @time_interval = '1h'
   end
 
   #returns true when http request to test_url returns a 200 OK Response
   def test_command
     begin
           response = Net::HTTP.get_response(URI.parse(test_url))
           @test_result = response.code
 
          if response.code != "200"
               return FALSE
         else
	          return TRUE
         end
 
     rescue Exception
            @test_result =  $! # $! global variable reference to the Exception object
            return FALSE
     end
 
  end
 
end

This test will also return FALSE ( test failed) when the http request encounters an Exception such as a Timeout::Error or a BAD URL. After each test the response code of the http request will be stored in the @test_result variable. When the http request encounters an Exception, the details of the exception is stored in the @test_result variable.

Now lets write some specific tests that monitors real websites using TestWebpageForHttp200.

class TestMySite < TestWebpageForHttp200
   def initialize
      @test_description  = "My Website Test"
      @test_url = "http://www.whisperservers.com/blog/"
      super
   end
end
 
class TestMyBlog < TestWebpageForHttp200
#tests my blog, to check if the blog is loading
 
   def initialize
      @test_description  = "My Blog Test"
      @test_url = "http://obi-akubue.homeunix.org/"
      super
   end
end
 
class TestFakeSite < TestWebpageForHttp200
#tests a website that doesn't exist this test will always fail
   def initialize
      @test_description  = "Fake website"
      @test_url = "http://wenosee.org/"
      super
   end
end
 
jobs = [ TestMySite.new, TestMyBlog.new, TestFakeSite.new]
 
puts "Welcome to Ragios"
puts "Initializing"
...
#schedule all the jobs to execute test_command() at every time_interval
scheduler = Rufus::Scheduler.start_new
jobs.each do |job|
    scheduler.every job.time_interval do
     begin
       if job.test_command
           puts job.test_description + "   [PASSED]" + " Created on: "+ Time.now.to_s
       else
           puts job.test_description +   "   [FAILED]" + " Created on: "+ Time.now.to_s
           job.failed
       end
       #catch all exceptions
      rescue Exception
          puts "ERROR: " +  $!  + " Created on: "+ Time.now.to_s
          job.error_handler
      end
   end #end of scheduler
end
 
#trap Ctrl-C to exit gracefully
puts "PRESS CTRL-C to QUIT"
  loop do
  trap("INT") { puts "\nExiting"; exit; }
    sleep(3)
  end

The tests in the code above will run every hour because they all extend TestWebpageForHttp200 which has time_interval set to ‘1h’. If we want to set any of the tests to a different time interval we simply set the time_interval attribute in its initialize method.

I included a test to a fake website that doesn’t exist, this test will always fail.

class TestFakeSite < TestWebpageForHttp200
#tests a website that doesn't exist this test will always fail
   def initialize
      @test_description  = "Fake website"
      @test_url = "http://wenosee.org/"
      super
   end
end

When this test fails the system admin will receive an alert message like this via email or twitter.

Fake website FAILED!
HTTP Request to http://wenosee.org/ = getaddrinfo: Name or service not known
Created on: Tue Oct 05 17:49:49 -0400 2010

Ragios is able to give the system admin very detailed information on what went wrong when a test fails.

View the complete source code here
ragios.rb: http://gist.github.com/608890
Edit: View the source for the Ragios system here: http://github.com/obi-a/Ragios

The Daemon
Now we need Ragios to run as a Daemon process. Luckily, we have the Daemons ruby gem for this.
To install the gem

sudo gem install daemons

Lets write a script to make ragios.rb run as a daemon.
ragiosd

#!/usr/bin/ruby
 
  require 'rubygems'
  require 'daemons'
 
  options = {
  :app_name   => "ragios",
  :log_output => true,
  :monitor    => true
}
Daemons.run('ragios.rb', options)

This script should be in the same folder with ragios.rb.
To start Ragios as a daemon, we simply run the script.

Start the daemon

ruby ragiosd start

Stop the daemon

ruby ragiosd stop

Restart the daemon

ruby ragiosd restart

Check Status of the daemon

ruby ragiosd status

Test the daemon

ruby ragiosd run

In the ragiosd script, we have set the daemon to log its output and monitor the process.

 options = {
  :app_name   => "ragios",
  :log_output => true,
  :monitor    => true
}

When we start the daemon it will log its output in a file called ragios.output in the same folder with ragiosd. It will also log its actions in a log file called ragios.log

View the source for ragiosd here:
http://github.com/obi-a/Ragios

 

Sending Tweet Alerts with St. Ruby

22 Sep

As a modern system we need St. Ruby (Ragios) to be able to tweet alerts to system admins and web masters when a test fails.

To do this, first we need to create and register an App on Twitter. This is the App that Ragios will use to tweet the alerts. So we create and register a twitter app from here: http://twitter.com/apps/new. After we register the App, Twitter will give us a consumer_key and a consumer_secret. We will need this later.

Next we need to create a new twitter account for the Ragios system. This is the Twitter account that will tweet the alerts. To receive the tweets the system admin should follow this account. Of course this account should be set to private on twitter.

After we create the account, we need to grant our twitter app access to it. Lets write a script to do that.

We need the oauth ruby gem.

sudo gem install oauth

This ruby script will do the trick;
twitter_auth.rb

#!/usr/bin/ruby
require 'rubygems'
require 'oauth'
 
consumer = OAuth::Consumer.new(
  'consumer key',
  'consumer secret',
  {:site => 'http://twitter.com'}
)
 
request_token = consumer.get_request_token
 
puts "Twitter App Authorize URL \n" + request_token.authorize_url
puts "Enter PIN:"
pin = STDIN.readline.chomp
 
access_token = request_token.get_access_token(:oauth_verifier => pin)
 
puts "access token: " + access_token.token
puts "access secret: " + access_token.secret

We use the ‘consumer_key’ and ‘consumer secret’ Twitter generated for our app. We need this to create a request_token which gives us an authorization URL. This is the URL which we use to ALLOW or DENY, the Twitter App access to the twitter account that will tweet the alerts.

The script will display the authorization URL for our App. Open this URL on a browser and click ALLOW to grant access. Twitter will give you a PIN number. Enter that PIN number on the prompt. This PIN number is our oauth_verifier which is used to generate the access_token.

The access_token and access_secret is all we need to gain read and write access to the twitter account. So we don’t need a twitter username and password to access the account. Thats the fun in using oauth. We need to save the access_token and access_secret somewhere to use later for tweeting.
This script from BeefyApps Blog, Simple Ruby OAuth with Twitter and this great post OAuth Explained and What It Is Good For, saved me a lot of trouble.

Now lets write a simple ruby script that tweets.

We need the twitter ruby gem;

sudo gem install twitter

Sample script 1:
For twitter gem v1.0 and above
tweet.rb

#!/usr/bin/ruby
require 'rubygems'
require 'twitter'
 
Twitter.configure do |config|
config.consumer_key = 'Consumer Key'
config.consumer_secret = 'Consumer secret'
config.oauth_token = 'access token'
config.oauth_token_secret = 'access secret'
end
 
Twitter.update("first tweet, this is a test")

We use the same ‘Consumer Key’ and ‘Consumer secret’ that Twitter generated for our App. We also use the ‘access token’ and ‘access secret’ we generated in the twitter_auth.rb script. The last line of the tweet.rb script will tweet the test message.

Sample script 2;
For twitter gem pre v1.0
[Edit March 13,2011] The code below only works with twitter gem below version 1.0. It doesn’t work with twitter gem version 1.0+ Thanks to @pablochacin for pointing this out in the comments. Note: Ragios uses twitter gem v0.9.12.

tweet1.rb

#!/usr/bin/ruby
require 'rubygems'
require 'twitter'
 
oauth = Twitter::OAuth.new('Consumer Key', 'Consumer secret')
oauth.authorize_from_access('access token', 'access secret')
 
client = Twitter::Base.new(oauth)
client.update('first tweet, this is a test')

Now lets add Tweet Alerts to our Ragios System
First, we need to create a new Class that knows how to tweet. This class will hide the dirty details of tweeting from the rest of the system.

#this class hides the messy details of tweeting from rest of the system
class Tweet
 
  def initialize
       oauth = Twitter::OAuth.new('Consumer Key', 'Consumer secret')
       oauth.authorize_from_access('access token', 'access secret')
 
       @client = Twitter::Base.new(oauth)
  end
 
 def tweet message
      @client.update(message)
 end
 
end

Note: I have changed the Naming convention for Ragios to use CamelCase for Class names and more_like_this for method names. Thanks to great tips here “Little Known Ways to Ruby Mastery by Jamie van Dyke”

Next we need to add a tweet_alert method to the SystemMonitor Class.

The tweet_alert method

def tweet_alert
 
     Tweet.new.tweet @test_description + " FAILED!  " + @describe_test_result + " = " + @test_result + " Created on:  " + Time.now.to_s
 end

The tweet_alert method is invoked by the failed method. The system admin can choose to use tweet alerts or email alerts by editing the failed method.

 #defines the action to take when a test fails
   #- May send email, SMS or tweet to the system admin
   #- May also take action to fix the issue like restart a process/service
   def failed
       tweet_alert
       #email_alert
   end

In the above sample, the System will send out a tweet when a test fails.

New SystemMonitor Class with the tweet_alert method

#base class that defines the behavior of all system monitors
class SystemMonitor
 
    # a short description of the test performed by this system monitor
   attr_reader :test_description
 
   #hostname of the system being monitored
   attr_reader :hostname
 
   #ip address of the system being monitored
   attr_reader :address
 
   #email address of admin to contact when a test fails
   attr_reader :contact
 
   #results of a test
   attr_reader :test_result
 
    #describes the test result, this gives technical details on the test_result
    #This gives the sysadmin info on the technical details of the test results
    attr_reader :describe_test_result
 
   def initialize
 
   end
 
   #defines the tests to run on a system
   def test_command
   end
 
   #defines the action to take when a test fails
   #- May send email, SMS or tweet to the system admin
   #- May also take action to fix the issue like restart a process/service
   def failed
       tweet_alert
       #email_alert
   end
 
  def tweet_alert
 
     Tweet.new.tweet @test_description + " FAILED!  " + @describe_test_result + " = " + @test_result + " Created on: "+ Time.now.to_s
 end
 
 
   def email_alert
       puts 'sending mail alert...'
       Pony.mail  :to => @contact,
                  :from => 'Ragios',
                  :subject => @test_description + " FAILED",
              :body => @test_description + " FAILED \n\n" + @describe_test_result + " = " + @test_result +  "\n\n Created on: " + Time.now.to_s
   end
end

Now lets test the system with a sample test, that monitors my website and alerts me (by posting a tweet) when the site is down.
This is the sample test. (The code is explained in more detail here)

#defines how services will be monitored
class Service < SystemMonitor
    def initialize
     super
    end
end
 
#monitors a webpage to check if the site is loading
#PASSED if it gets a HTTP 200 Response status code from the website
class TestWebpageForHttp200 < Service
 
   attr_reader :test_url
 
   def initialize
        @contact = "obi@mail.com"
        @describe_test_result = "HTTP Request to " + @test_url
        super
   end
 
   #returns true when http request to test_url returns a 200 OK Response
   def test_command
       response = Net::HTTP.get_response(URI.parse(test_url))
        @test_result = response.code
       if response.code != "200"
            return FALSE
       else
	    return TRUE
       end
   end
 
end
 
class TestMySite < TestWebpageForHttp200
   def initialize
      @test_description  = "My Website Test"
      @test_url = "http://www.whisperservers.com/blog/"
      super
   end
end

When this test fails the system will tweet a message like this;

My Website Test FAILED! HTTP Request to http://www.whisperservers.com/blog/ = 500
Created on: Wed Sep 22 13:55:21 -0400 2010

So we are now all set with Tweet Alerts for St. Ruby.

Source for Ragios:http://github.com/obi-a/Ragios.

 

Adding Email Alert to Ragios (St. Ruby)

19 Sep

In the last blog post, I started working on St. Ruby, an Object Oriented Ruby Based Network and System Monitoring System. Its just for fun and mostly an excuse to play with ruby and Linux servers.

I have added Email alert to Ragios. Anytime a test fails Ragios fires up an email to the system admin.

We are using the Pony ruby gem to send the email alerts.

To install the Pony gem;

sudo gem install pony

We are using sendmail for mail transport; Installing sendmail on Ubuntu;

sudo apt-get install sendmail

Testing sendmail to verify it works

echo "Subject: test" | /usr/lib/sendmail -v me@domain.com

(courtesy of cool commands)

Sample code to send email with Pony via sendmail;

#!/usr/bin/ruby
require 'rubygems'
require 'pony'
puts 'sending mail...'
Pony.mail :to => 'test@example.com',
          :from => 'obi',
          :subject => 'here we get near yeah yeah!',
          :body => 'wsup!'

Ragios Email Alert
To add the email alert to Ragios we just needed to add a new method called email_alert to the System Monitor Class. This method is invoked by the failed method. Ragios runs the failed method anytime a test fails in the system.

The email_alert method

 def email_alert
       puts 'sending mail alert...'
       Pony.mail  :to => @contact,
                  :from => 'Ragios',
                  :subject => @test_description + " FAILED",
              :body => @test_description + " FAILED \n\n" + @describe_test_result + " = " + @test_result
   end

We also added a new attribute @decribe_test_result, this describes the meaning of @test_result, this is very useful in reporting to the system admin what exactly what went wrong. More on this later.

The new System monitor class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#base class that defines the behavior of all system monitors
class System_monitor
 
    # a short description of the test performed by this system monitor
   attr_reader :test_description
 
   #hostname of the system being monitored
   attr_reader :hostname
 
   #ip address of the system being monitored
   attr_reader :address
 
   #email address of admin to contact when a test fails
   attr_reader :contact
 
   #results of a test
   attr_reader :test_result
 
    #describes the test result, this gives technical details on the test_result
    #This gives the sysadmin info on the technical details of the test results
    attr_reader :describe_test_result
 
   def initialize
 
   end
 
   #defines the tests to run on a system
   def test_command
   end
 
   #defines the action to take when a test fails
   #- May send email or SMS to the admin under contact
   #- May also take action to fix the issue like restart a process/service
   def failed
       email_alert
   end
 
   def email_alert
       puts 'sending mail alert...'
       Pony.mail  :to => @contact,
                  :from => 'Ragios',
                  :subject => @test_description + " FAILED",
              :body => @test_description + " FAILED \n\n" + @describe_test_result + " = " + @test_result
   end
end

On the last post we had a sample test class Test_webpage_for_http_200 , that tests a website to see if the home page is loading, it returns PASSED when the home page loads and FAILED when the site is down. Now that we have an email alert, we just need to add a contact email address to be alerted when the test fails.

New Test_webpage_for_http_200 class

#monitors a webpage to check if the site is loading
#PASSED if it gets a HTTP 200 Response status code from the website
class Test_webpage_for_http_200 < Service
 
   attr_reader :test_url
 
   def initialize
        @contact = "obi@mail.com"
        @describe_test_result = "HTTP Request to " + @test_url
        super
   end
 
   #returns true when http request to test_url returns a 200 OK Response
   def test_command
       response = Net::HTTP.get_response(URI.parse(test_url))
        @test_result = response.code
       if response.code != "200"
            return FALSE
       else
	    return TRUE
       end
   end
 
end

If we wanted to use the same contact email for all service tests, we simply assign the email address to @contact on the Service class. If we wanted a system wide contact email we just initialize @contact on the System_monitor class which is the base class of the system.

A specific test on my website looks like this;

class Test_my_site < Test_webpage_for_http_200
   def initialize
      @test_description  = "My Website Test"
      @test_url = "http://www.whisperservers.com/blog/"
      super
   end
end

An Email Alert from Ragios when this test fails will looks like this;

    From: Ragios@domain.com
        To: obi@mail.com
 
My Website Test FAILED
 
HTTP Request to http://www.whisperservers.com/blog/ = 500

This tells the site admin exactly what is going on.

Edit: View the most recent source code here: http://github.com/obi-a/Ragios

New Ragios complete Source code with Email Alert;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/ruby
#:Title   :Ragios (aka St. Ruby)
#:Date    :9/16/2010
#:Author  :Obi Akubue
#:Version :0.2
#description: This is the framework for a Ruby Based System and Network Monitoring Tool
 
 
require 'net/http'
require 'rubygems'
require 'pony'
 
#base class that defines the behavior of all system monitors
class System_monitor
 
    # a short description of the test performed by this system monitor
   attr_reader :test_description
 
   #hostname of the system being monitored
   attr_reader :hostname
 
   #ip address of the system being monitored
   attr_reader :address
 
   #email address of admin to contact when a test fails
   attr_reader :contact
 
   #results of a test
   attr_reader :test_result
 
    #describes the test result, this gives technical details on the test_result
    #This gives the sysadmin info on the technical details of the test results
    attr_reader :describe_test_result
 
   def initialize
 
   end
 
   #defines the tests to run on a system
   def test_command
   end
 
   #defines the action to take when a test fails
   #- May send email or SMS to the admin under contact
   #- May also take action to fix the issue like restart a process/service
   def failed
       email_alert
   end
 
   def email_alert
       puts 'sending mail alert...'
       Pony.mail  :to => @contact,
                  :from => 'Ragios',
                  :subject => @test_description + " FAILED",
              :body => @test_description + " FAILED \n\n" + @describe_test_result + " = " + @test_result
   end
end
 
#defines how computers,servers,network devices will be monitored
class Host < System_monitor
    def initialize
     super
    end
 
end
 
#defines how services will be monitored
class Service < System_monitor
    def initialize
     super
    end
end
 
 
#monitors a webpage to check if the site is loading
#PASSED if it gets a HTTP 200 Response status code from the website
class Test_webpage_for_http_200 < Service
 
   attr_reader :test_url
 
   def initialize
        @contact = "obi@mail.com"
        @describe_test_result = "HTTP Request to " + @test_url
        super
   end
 
   #returns true when http request to test_url returns a 200 OK Response
   def test_command
       response = Net::HTTP.get_response(URI.parse(test_url))
        @test_result = response.code
       if response.code != "200"
            return FALSE
       else
	    return TRUE
       end
   end
 
end
 
class Test_my_site < Test_webpage_for_http_200
   def initialize
      @test_description  = "My Website Test"
      @test_url = "http://www.whisperservers.com/blog/"
      super
   end
end
 
class Test_my_blog < Test_webpage_for_http_200
#tests my blog, to check if the blog is loading
 
   def initialize
      @test_description  = "My Blog Test"
      @test_url = "http://obi-akubue.homeunix.org/"
      super
   end
end
 
 
jobs = [ Test_my_site.new, Test_my_blog.new]
 
jobs.each do |job|
 puts job.test_description
 if job.test_command
        puts "   [PASSED]"
     else
        puts "   [FAILED]"
        job.failed
     end
end

[UPDATE 10-1-2010] View the complete Ragios source with latest revisions
http://github.com/obi-a/Ragios.

 
 

[DEPRECATED]Ragios: Ruby based System and Network Monitoring Tool

31 Aug

This post has been deprecated. See the new version of Ragios here: http://github.com/obi-a/Ragios

While reading the book “Nagios: system and Network Monitoring” by Wolfgang Barth, I thought it will be a good idea to write a Ruby based Object Oriented System and Network Monitoring tool similar to Nagios.

So I started writing such a tool. Since it was inspired by Nagios, I will call it Ragios (Ruby Agios) aka Saint Ruby (St. Ruby) since Agios is Saint in Greek.

This is all just for fun and educational purposes.

Ragios could be used to monitor any type of system including servers, workstations, switches, routers, system services and applications, locally or over a network. The system admin can define the tests he wants to run on the system or re-use tests written by other developers. The tests run periodically on the system. When a test fails the admin receives an email or SMS alert from Ragios. Everything is written in ruby, the configuration settings are all in ruby syntax and Ragios itself is a ruby script.

Ragios is Object Oriented so everything is an object. The Base object is the System_monitor defined by the System_monitor class. This class defines the behavior of all system monitors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class System_monitor
#base class that defines the behavior of all system monitors
 
   attr_reader :test_description   # a short description of the test performed by this system monitor
   attr_reader :hostname #hostname of the system being monitored
   attr_reader :address   #ip address of the system being monitored
   attr_reader :contact    #email address of admin to contact when a test fails
   attr_reader :test_result #results of a test
 
   def initialize
   end
 
   def test_command
   #defines the tests to run on a system
   end
 
   def failed
   #defines the action to take when a test fails
   #- May send email or SMS to the admin under contact
   #- May also take action to fix the issue like restart a process/service
   end
end

The method test_command defines the test that will be performed on the system periodically by the system monitor. If the test is successful test_command will return TRUE, if it fails the method will return FALSE. The test_command method can run any type of test, it just needs to return values TRUE for a PASSED test and FALSE for a FAILED test.

The failed method defines the actions to be performed when a test fails. These actions may include sending email or SMS to alert the system admin about a problem. It may also include actions to fix the problem.

After every test any results from the test like an error message for a failed test is saved in the test_result variable. This should be implemented in the test_command method.

Ragios monitors 2 types of systems, Hosts and Services. Hosts are devices that run on a network like computers, routers, switches and servers. Services are applications and processes like a web server, database, web apps, and system processes.

Hosts and Services both extend the System_monitor class. They both inherit all the characteristics of a System_monitor.

The Host class

1
2
3
4
5
6
7
class Host < System_monitor
#defines how computers,servers,network devices will be monitored
 
    def initialize
     super
    end
end

The Service class

1
2
3
4
5
6
class Service < System_monitor
#defines how services, processes and applications will be monitored
    def initialize
     super
    end
end

Now we have the basic framework in place. With Ragios the system admin implements his own system monitors or reuses system monitors already implemented by other developers.

Lets implement a simple system monitor that monitors a webpage and alerts the owner when the site is down. This is simply done by sending http requests to the site’s home page and alerting the site owner if it fails to get a HTTP 200 OK status response from the server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Test_webpage_for_http_200 < Service
#monitors a webpage to check if the site is loading
#PASSED if it gets a HTTP 200 Response status code from the website
 
   attr_reader :test_url
 
   def initialize
        super
   end
 
   def test_command
     #returns true when http request to test_url returns a 200 OK Response
       response = Net::HTTP.get_response(URI.parse(test_url))
        @test_result = response.code
       if response.code != "200"
            return FALSE
       else
	    return TRUE
       end
   end
 
   def failed
         #send email notification to site owner
         #not yet implemented
   end
end

Test_webpage_for_http_200 extends the Service class because it is testing http which is a service. it also has all the characteristics of the base class System_monitor. We just needed to override the test_command method to implement our specific test.

def test_command
     #returns true when http request to test_url returns a 200 OK Response
       response = Net::HTTP.get_response(URI.parse(test_url))
        @test_result = response.code
       if response.code != "200"
            return FALSE
       else
	    return TRUE
       end
   end

test_command sends http requests to the test_url and returns TRUE when it gets a 200 OK Response, returns FALSE when it gets a different response code. The response code is saved in @test_result as the result of this test. This value gives a system admin insight on what has gone wrong.

The failed method should define the actions to take when a test fails. In this case it sends an email to notify the site owner. The email feature is not yet implemented.

Test_webpage_for_http_200 is a generic system monitor, it doesn’t test any particular site, we still need to write system monitors that test specific sites for us. These monitors will be subclasses of Test_webpage_for_http_200. Lets write some now

1
2
3
4
5
6
7
8
class Test_my_blog < Test_webpage_for_http_200
#monitors my blog, to check if the blog's home page is loading
   def initialize
      @test_description  = "Testing My Blog"
      @test_url = "http://obi-akubue.homeunix.org/"
      super
   end
end

Running

Test_my_blog.new.test_command

will send a http request to my blog’s home page http://obi-akubue.homeunix.org/ and return TRUE if it gets a 200 Ok Response and FALSE if it gets anything else.

Lets write another test, this one monitors my website http://whisperservers.com/blog.

1
2
3
4
5
6
7
class Test_my_site < Test_webpage_for_http_200
   def initialize
      @test_description  = "Testing my website site"
      @test_url = "http://www.whisperservers.com/blog/"
      super
   end
end

Running

Test_my_site.new.test_command

will send a http request to my site’s home page http://www.whisperservers.com/blog/ and return TRUE if it gets a 200 Ok Response and FALSE if it gets anything else.

Ragios will run all our tests and alert us when a test fails.

1
2
3
4
5
6
7
8
9
10
11
jobs = [Test_my_blog.new, Test_my_site.new]
 
jobs.each do |job|
 puts job.test_description
 if job.test_command
        puts "   [PASSED]"
     else
         puts "   [FAILED]"
         job.failed
     end
end

We just need to add our tests to the jobs Array.

jobs = [Test_my_blog.new, Test_my_site.new]

Ragios will alert us when a test fails by calling the failed method.

Complete source code for Ragios

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/ruby
#:Title   :Ragios (aka St. Ruby)
#:Date    :8/26/2010
#:Author  :Obi Akubue
#:Version :0.1
#description: This is the framework for a Ruby Based System and Network Monitoring Tool
 
 
require 'net/http'
 
class System_monitor
#base class that defines the behavior of all system monitors
 
   attr_reader :test_description   # a short description of the test performed by this system monitor
   attr_reader :hostname #hostname of the system being monitored
   attr_reader :address   #ip address of the system being monitored
   attr_reader :contact    #email address of admin to contact when a test fails
   attr_reader :test_result #results of a test
 
   def initialize
   end
 
   def test_command
   #defines the tests to run on a system
   end
 
   def failed
   #defines the action to take when a test fails
   #- May send email or SMS to the admin under contact
   #- May also take action to fix the issue like restart a process/service
   end
end
 
 
class Host < System_monitor
#defines how computers,servers,network devices will be monitored
 
    def initialize
     super
    end
 
end
 
class Service < System_monitor
#defines how services will be monitored
 
    def initialize
     super
    end
end
 
class Test_webpage_for_http_200 < Service
#monitors a webpage to check if the site is loading
#PASSED if it gets a HTTP 200 Response status code from the website
 
   attr_reader :test_url
 
   def initialize
        @contact = "Obi@whisperservers.com"
        super
   end
 
   def test_command
     #returns true when http request to test_url returns a 200 OK Response
       response = Net::HTTP.get_response(URI.parse(test_url))
        @test_result = response.code
       if response.code != "200"
            return FALSE
       else
	    return TRUE
       end
   end
 
   def failed
         #send email notification to site owner @contact
         #not yet implemented
   end
end
 
class Test_my_site < Test_webpage_for_http_200
   def initialize
      @test_description  = "Testing my website site"
      @test_url = "http://www.whisperservers.com/blog/"
      super
   end
end
 
class Test_my_blog < Test_webpage_for_http_200
#tests my blog, to check if the blog is loading
 
   def initialize
      @test_description  = "Testing My Blog"
      @test_url = "http://obi-akubue.homeunix.org/"
      super
   end
end
 
 
jobs = [ Test_my_site.new, Test_my_blog.new]
 
jobs.each do |job|
 puts job.test_description
 if job.test_command
        puts "   [PASSED]"
     else
        puts "   [FAILED]"
        job.failed
     end
end

In its current form Ragios is just a simple ruby script, the system admin has to edit this script to add tests and configuration settings, or reuse tests already available.

Any setting that applies to more than one test should be added to the initialize method of the super class of those tests. In the example above we added

@contact = "Obi@whisperservers.com"

to the initialize method of Test_webpage_for_http_200. This allows our tests (Test_my_blog and Test_my_site) to use the same contact = "obi@whisperservers.com" by simply calling the super method in their constructor.

Ragios is still incomplete, for now we may set it to run hourly as a cron job or in the future we may make it into a daemon. This is just the basic framework to extend and play with.

[UPDATE 10-1-2010] View the complete Ragios source with latest revisions
http://github.com/obi-a/Ragios.

 

Installing Rails + Apache + Passenger on Ubuntu 10.04 with Speedtrain

08 Aug

[Update 3/7/2011] Check the updated version of the speedtrain script for Ruby 1.9.2 and Rails 3 here: http://obi-akubue.org/?p=922 and https://github.com/obi-a/speedtrain. This version doesn’t install Apache, Passenger yet.

I have written a new version of the Speedtrain script. This version now includes an option to install Rails with Apache and Phusion Passenger ready for production. By default the script will install Ruby, Rubygems, Rails, Sqlite and a Sample app. But by using the advanced option, the script will also install apache and phusion passenger with directions to deploy the Sample app on passenger.

Usage:
Step 1. Download the script

wget http://whisperservers.com/speedtrain

Step 2. Make the script executable

chmod +x speedtrain

Step 3. Option 1
For a basic rails setup for development, which install Rails (Ruby,Rubygems) and Sqlite. simply run the script

./speedtrain

Option 2. For a production type Rails setup, which install Rails (Ruby,Rubygems), Sqlite, Apache and Phusion Passenger run the script with a -p switch.

./speedtrain -p

After the installation the script will create a folder in your $HOME directory called rails_apps. This is the folder where you can create and store your rails apps. The folder is at $HOME/rails_apps. The script will also create a sample Rails app at $HOME/rails_apps/test_app. You can run the sample app by typing

cd $HOME/rails_apps/testapp
ruby script/server

Then open your browser and type http://localhost:3000/

If you used the option to install Apache and Passenger, you will be guided interactively through the Apache + Passenger installation. After the installation, follow the simple steps displayed on the screen to deploy Rails apps on passenger. Very easy steps:)

This script is ready to run on most Ubuntu 10.04 installations. Works great and easy on ubuntu as host OS on a machine. Using virtual box Apache gets some permission issues but should be easy to fix if one digs deeper. It works perfectly on Amazon EC2 Ubuntu 10.04 instances.

To install Rails with Passenger on an EC2 instance with this script you can use this Ubuntu AMI image# ami-2d4aa444 or choose one from here

Using these AMIs the username is literally “ubuntu” as in
ssh -i yourkeyname.pem ubuntu@ec2-123-45-67-89.compute-1.amazonaws.com. I found this in the comments after some digging.

Have fun.

The source code for the new speedtrain script.

#!/bin/bash
#:Title   :Speedtrain on Rails
#:Date    :
#:Author  :Obi Akubue
#:Version :0.1
#:Description: This script installs Ruby on Rails on Ubuntu 10.04 with the option to install Apache and Phusion Passenger. (It creates a test rails app)
 
#Usage Option 1: To Install Rails (Ruby + Rubygems) + sqlite. Simply run the script by typing ./speedtrain
#Usage Option 2: To Install Rails (Ruby + Rubygems) + Sqlite + Apache + Passenger. Run script by typing ./speedtrain -p
 
red='\e[0;31m'
RED='\e[1;31m'
blue='\e[0;34m'
BLUE='\e[1;34m' #light blue
cyan='\e[0;36m'
CYAN='\e[1;36m'
GREEN='\e[1;32m'
YELLOW='\e[1;33m'
WHITE='\e[1;37m'
NC='\e[0m' # No Color
 
#begining  messages
 if [ "$1" = "-p" ]; then
    #option to install Apache + Passenger
        echo  -e "${GREEN} Welcome to Speedtrain on Rails"
        echo " Installing Rails (Ruby + Rubygems) + Apache + sqlite + passenger ..."
        echo " This will take a few minutes to complete.."
        echo -e "${WHITE} Press ENTER to continue or Ctrl-C to Quit"
 
        echo -e "${NC}"
 
    else
        echo  -e "${GREEN} Welcome to Speedtrain on Rails"
        echo " Installing Rails..."
        echo " This will take a few minutes to complete.."
        echo -e "${WHITE} Press ENTER to continue or Ctrl-C to Quit"
        echo -e "${NC}"
   fi
 
 read key
 
echo -e "${RED} updating system..."
echo -e "${CYAN}"
sudo aptitude update
 
echo -e "${RED} Installing build essential..."
echo -e "${CYAN}"
sudo apt-get install build-essential
 
echo -e "${RED} installing ruby..."
echo -e "${GREEN}"
sudo apt-get install irb libopenssl-ruby libreadline-ruby rdoc ri ruby ruby-dev
 
echo -e "${RED} installing rubygems..."
echo -e "${CYAN}"
cd /usr/local/src
sudo wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.6.tgz
sudo tar xzvf rubygems-1.3.6.tgz
cd rubygems-1.3.6
sudo ruby setup.rb
 
echo -e "${RED} updating rubygems..."
echo -e "${GREEN}"
sudo update-alternatives --install /usr/bin/gem gem /usr/bin/gem1.8 1
sudo gem update --system
 
echo -e "${RED} installing rails..."
echo -e "${CYAN}"
sudo gem install rails
 
echo -e "${RED} installing sqlite..."
echo -e "${GREEN}"
sudo apt-get install libsqlite3-dev sqlite3 sqlite3-doc
sudo gem install sqlite3-ruby
 
echo -e "${RED} creating dev directory..."
echo -e "${CYAN}"
mkdir ~/rails_apps/
 
cd ~/rails_apps/
echo -e "${RED} creating dev test app..."
echo -e "${GREEN}"
rails testapp
 
if [ "$1" = "-p" ]; then
#if the passenger switch is set
echo -e "${RED} installing Apache..."
echo -e "${CYAN}"
sudo apt-get install apache2
 
echo -e "${RED} installing passenger..."
echo -e "${GREEN}"
sudo gem install passenger
 
#install apache development headers
#required by passenger
#Apache 2 development headers --
sudo apt-get install apache2-prefork-dev
 
#Apache portable Runime (APR) development headers --
sudo apt-get install libapr1-dev
#install passenger
sudo passenger-install-apache2-module
fi
 
#ending message
if [ "$1" = "-p" ]; then
#if the passenger switch is set
echo -e "${YELLOW}"
printf "Your Apache Configuration file is /etc/apache2/httpd.conf\n"
echo -e "${NC}"
fi
 
echo -e "${CYAN}"
echo "Rails has been successfully installed"
echo -e "${GREEN}"
echo "Your Apps directory is $HOME/rails_apps"
echo "We created a Test Rails App for you at $HOME/rails_apps/testapp/"
echo "To run the Test App type"
echo -e "${YELLOW} cd $HOME/rails_apps/testapp"
echo " ruby script/server"
echo -e "${NC}"
 
if [ "$1" = "-p" ]; then
#if the passenger switch is set
echo -e "${GREEN}"
echo "To deploy the Test Rails app on passenger "
echo "Edit the Apache Configuration file and add the following virtualhost"
echo -e "${YELLOW}\n"
 
echo ""
echo "  ServerName www.yourhost.com"
echo "  DocumentRoot $HOME/rails_apps/testapp/public"
echo " "
echo "     AllowOverride all"
echo "     Options -MultiViews"
echo " "
echo ""
echo -e "${NC}"
echo -e "${GREEN}"
echo "then Restart Apache: sudo /etc/init.d/apache2 restart"
echo "and Open on your browser: http://yourdormain.com or http://your-ip.com"
echo -e "${NC}"
fi
 
 
 
Premium Wordpress Plugin