Wednesday, December 03, 2008

Rails Deployment: Capistrano + GitHub + Amazon EC2

I have been working on my personal stamp project for a few days now and got some basic application running. As till now, I am able to create entries for stamp and have a cart like application. Since the application is running, I thought why not deploy it and remain agile. So I started working on rails deployment. There were many options including building my own powerful server (which I am planning to anyways) but I wanted to have a quick start. What a better place then Amazon Web Services Elastic Cloud Computing (EC2) where I started a Ubuntu image and started customizing it. I used git as version control for my project and used github to host my repository. Also used Capistrano for rails deployment. In this post, I will give details steps of how to combine the power of Capistrano, github, MySQL (other database can be used) and Amazon EC2 to deploy your rails application quickly therefore remaining agile.
I have assumed that you have an AWS account and have you machine setup to run ec2 tools or have ElasticFox plugin for Firefox.

CONFIGURING EC2 INSTANCE
I used Ubuntu gutsy image and started an instance.
ssh to the instance. Generally, ruby is already installed on the instance so we should start installing other ruby packages.
Install RubyGems from source
wget http://rubyforge.org/frs/download.php/43985/rubygems-1.3.0.tgz
tar -xvzf rubygems-1.3.0.tgz
cd rubygems-1.3.0
sudo ruby setup.rb

Create a symbolic link to gem1.8
sudo ln -s /usr/bin/gem1.8 /usr/bin/gem

and update RubyGems
sudo gem update –system

Use RubyGems to install rails and other packages. Also install mysql server and driver plus
sudo apt-get install mysql-server libmysql-ruby libmysqlclient15-dev libc6-dev git-core

During mysql-server installation root password will be asked. It is recommended that a password be assigned.
sudo gem install rails mongrel termios mongrel_cluster mysql

Now is the time to create database in mysql for production and grant privileges. Login into
mysql as root and using root password.
mysql –u root –p
mysql>CREATE DATABASE myapp;
mysql> GRANT ALL PRIVILEGES ON myapp.* TO ‘myapp’@’localhost’ IDENTIFIED BY 'myapp_password';

Create directory for deploy. I created /var/www

INSTALLING APACHE ON EC2 INSTANCE
wget http://mirror.olnevhost.net/pub/apache/httpd/httpd-2.2.10.tar.gz
tar –xvf httpd-2.2.10.tar.gz
cd httpd-2.2.10
./configure --prefix=/usr/local/apache --enable-proxy --enable-proxy-http --enable-proxy-balancer --enable-dav --enable-rewrite --enable-so --enable-http --enable-expires --enable-headers --enable-mods=deflate_module --with-php --with-mysql --with-susexec --disable-info --without-berkeley-db --enable-dav=shared --enable-dav-lock=shared --with-included-apr
make
sudo make install

GITHUB AND GIT

At this point, we should have our git repository at github. Go to GitHub and create an account. Follow the instruction to add source control to your application. At this point we will need to create public-private keypair for local machine as well as each production server. Put the private key in the EC2 instance and add the public key to the github account for both local and EC2 instance. Put the private key in .ssh folder. You can use
ssh-keygen

to generate keys on EC2 instance and you local server. Do not change the name of the keypair and let it be named to the default (id_rsa and id_rsa.pub). Also don’t associate any paraphrase for the key.

CONFIGURING MONGREL TO RUN IN CLUSTER AND CONFIGURING OTHER FILES

Run the following command
sudo mongrel_rails cluster::configure –e production –p 8000 –a 127.0.0.1 –N 2 –c /deploy/path/current

Here config/mongrel_cluster.yml file will be created with configuration information for mongrel to start. –N here is for starting 2 mongrel servers. Also make sure that you add current to the end of the deploy path above.
Change database.yml and change username, password and database for production.
In config/environment.rb comment out the following line
RAILS_GEM_VERSION = '2.1.2' unless defined? RAILS_GEM_VERSION

This will cause the gem to use the latest version installed rather than a previous version which might cause some problems when you have update gem version.
In config/environments/production.rb comment out the following
config.action_view.cache_template_loading


INSTALLING CAPISTRANO ON LOCAL MACHINE

On your local machine install Capistrano
sudo gem install capistrano
This will install Capistrano 2.5.2 Now we need to “capify” the application. Goto to application’s root directory and type
capify

This will create two files
1. Capfile: This is the main file which cap need similar to rakefile for rake
2. Config/deploy.rb: This contains all the configuration data for rails application deployment

require 'mongrel_cluster/recipes'
set :application, "app_name
set :repository, "git://github.com/username/projectname.git "

# If you aren't deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
set :deploy_to, "/var/www/#{application}"
set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"

# If you aren't using Subversion to manage your source code, specify
# your SCM below:
set :scm, :git
server "application.com", :app, :web, :db, :primary => true
set :user, 'root'
ssh_options[:port] = 22
ssh_options[:verbose] = :debug
ssh_options[:username] = 'root'
ssh_options[:host_key] = 'ssh-dss'
ssh_options[:keys] = "path/to/key"
ssh_options[:paranoid] = false

set :use_sudo, false

DEPLOYMENT
For the first time when you are deploying for the first time, run the command
cap deploy:cold
subsequently
cap deploy
After this, one can bundle the instance and create an image so that more instance can be started any time.

This summarizes the configuration and deployment of rails application on the cloud. Using GitHub and Amazon EC2, rails deployment is quick and cheap. One can start with EC2 and then add real servers + more instances.

Next to come is MySQL on Elastic Block Storage (Amazon EBS) so that database is persistent.

Labels: , , , ,