Deploying a Rails Application to Production on Amazon EC2

Building webapps with Ruby on Rails can be super easy once you learn some basics. Deploying your Rails application to production … that has traditionally been really tough.

One good option is to deploy to Amazon EC2 using EC2 for Rails. EC2 on Rails is a set of Capistrano recipes as well as an Amazon Machine Image (AMI) from which to build your EC2 instance.

EC2 on Rails is great. Unfortunately, if you’ve never used EC2 before, you probably won’t be able to “Deploy a Ruby on Rails app on EC2 in Five Minutes” as the documentation claims, so this document will try to fill in the gaps for someone who has never worked with EC2.

The core information on running an EC2 instance can be found on the EC2 site, particularly Getting Started Guide, Chapter 5: Running an Instance.

This article will aim to be a comprehensive, all-inclusive, step-by-step guide to building and deploying a simple Rails application on EC2.

Prequisites on Your Development Machine

  1. Ruby and Rails installed. As of this writing, please make sure that you are using Rails 2.1.0
  2. MySQL installed
  3. Java Development Kit 1.5 or later installed (Mac users should be ready-to-go, Windows/Linux users if you don’t have it, download it from http://java.sun.com/javase/downloads/index.jsp) Make sure to download a version labeled “JDK”. Java is required for the tools that Amazon provides to manage EC2 instances. There are pure Ruby options as well, but I am going to stick with the Amazon provided tools for this guide.

Sign up for Amazon EC2

Amazon Elastic Compute Cloud (Amazon EC2) is a web service that “provides resizable compute capacity in the cloud”.

Sign up for EC2 at http://aws.amazon.com/ec2/.

Sign Up for Amazon S3

S3 is Amazon’s “Simple Storage Service”. S3 is a super-inexpensive service to store files into “buckets in the cloud”. S3 will be used for database backups of your Rails Application.

Sign up for S3 here: http://aws.amazon.com/s3/

Collect Your Account Identification Information


After signing up, you will need to collect four pieces of information from your AWS account by visiting the Access Identifiers page.

  1. Your account number. The account number can be found at the upper right of the Access Idenfiers page and should be three four-digit numbers separated by dashes.
  2. Your Access Key ID. This is a 20 or so character key found in a beige box a little below your account number.
  3. Your Secret Access Key. This is a 40 or so character key found in another beige box just below your Access Key ID. If this is your first time on this page, you may have to generate your key. Click the “Show” button to display your 40 character key.
  4. Your X.509 Certificate Create and download the X.509 certificate below the Secret Access Key section. Place the public and private keys into a folder called “.ec2″ in your home directory.

Download and Install the EC2 Command Line Tools

The EC2 command-line tools are a Java-based set of tools that allow you to create and manage machine instances on EC2.

Download the Command Line Tools
Download tools here: Amazon EC2 Command-Line Tools

Extract the Downloaded ZIP
XXXXXXXXXXXXXXXXXXXX

Set Appropriate Environment Variables
export EC2_PRIVATE_KEY=/Users/rlambert/.ec2/pk-5xxxxxxxx7.pem
export EC2_CERT=/Users/rlambert/.ec2/cert-5xxxxxxxxxxxxx7.pem
export EC2_HOME=/Applications/java/ec2-api-tools-1.3-24159
export PATH=$EC2_HOME/bin:$PATH

Create a Key Pair for Your Computer from which you will be deploying EC2 Instances

ec2-add-keypair ec2-rails-keypair

The string ec2-rails-keypair can be anything that you like, try to pick something that makes sense for your setup. Anywhere in this document that you see ec2-rails-keypair, replace if with the string that you picked if you decide to use something different.

Save the output from that into a file named id_rsa-ec2-rails-keypair and paste everything between (and including) the “—–BEGIN RSA PRIVATE KEY—–” and “—–END RSA PRIVATE KEY—–” lines into it. Confirm that the file contents looks exactly like this, then save the file into the file ~/.ssh/id_rsa-ec2-rails-keypair

Set permissions on the new key file:

chmod 600 ~/.ssh/id_rsa-ec2-rails-keypair

Start Up an Amazon EC2 Instance

An Amazon Machine Image (AMI) is a named configuration of an EC2 image.

The current AMI id’s for EC2onRails are:

  • ami-c9bc58a0 (32-bit)
  • ami-cbbc58a2 (64-bit)

Let’s start up an instance of the 32-bit EC2onRails image:

ec2-run-instances ami-c9bc58a0 -k ec2-rails-keypair

The second line of the results returned will look like:

INSTANCE	i-XXXXXXXX	ami-c9bc58a0			pending	ec2-rails-keypair	0

The pending ec2-rails-keypair means that the image is pending.
To check the status of the instance build type:

ec2-describe-instances i-XXXXXXXX

Replace the i-XXXXXXXX above with the string that comes after INSTANCE in the second line of the results from the ec2-run-instances command.
When the sixth column of the returned “describe” data says running ec2-rails-keypair, you have an Amazon EC2 instance running! You’ve got your own Linux box running in the sky!

Take note of the string that looks like ec2-xx-xxx-xxx-xx.compute-1.amazonaws.com, that is your machine’s address.

AUTHORIZE SSH AND HTTP ACCESS TO PORTS 22/80 RESPECTIVELY

ec2-authorize default -p 22

This should return something like:
PERMISSION default ALLOWS tcp 22 22 FROM CIDR 0.0.0.0/0

ec2-authorize default -p 80

This should return something like:
PERMISSION default ALLOWS tcp 80 80 FROM CIDR 0.0.0.0/0

Boom! You’ve got a server in the cloud, ready to go!

You should be able to ssh into the your new machine, replace ec2-xx-xxx-xxx-xx.compute-1.amazonaws.com with your own machine’s address:

ssh -i ~/.ssh/id_rsa-ec2-rails-keypair root@ec2-xx-xxx-xxx-xx.compute-1.amazonaws.com

You may have to type “yes” to accept the authenticity of the host. After that you should be in!

Build a Normal Rails Application

rails -d mysql demo
cd demo
ruby script/generate scaffold Widget name:string description:string date_available:datetime size:float

Edit your development connection login and password in config/database.yml and create a MySQL local database called demo_development.

Start it up …

ruby script/server

You should be able to go to http://localhost:3000/widgets and perform simple CRUD on the widget objects.

That’s our simple application … so far nothing specific to EC2 …

Preparation of Your Rail Application for EC2

EC2 for Rails requires Capistrano, for some reason, I had to install version 2.4.3:

sudo gem install capistrano -v 2.4.3

And then install the EC2 for Rails gem:

sudo gem install ec2onrails

Okay, you need to add three configuration files to your Rails application.

  1. Capfile - save this file at the root of your application
  2. deploy.rb - save this file in the config folder
  3. s3.yml - also save this file in the config folder

Customize the EC2 Configurations

Capfile can be left as-downloaded.

config/s3.yml - This configuration is pretty simple, under the production section, put your AWS information that you noted above. The aws_access_key should be a 20-character string and the aws_secret_access_key should be a 40-character string. Set the bucket_base_name to a world-wide globally unique name for your production data backups; you probably want to end the string with your domain name to help ensure uniqueness across S3. In the end, it should look something like

production:
  aws_access_key: 11BBBBBBBBBBBBBBBBB2
  aws_secret_access_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  bucket_base_name: production.yourcompany.com

config/deploy.rb - Deploy.rb has quite a bit of possible configurations but it is pretty well documented, so really read all of the comments in that file. At a minimum you will probably have to change:

  • TODO …. fill these out, tell which ones you can probably comment out, mention how to configure SVN pswds

config/database.yml - For the production section, basically add any good password that you like and add hostname: db_primary. It should look something like:

production:
  adapter: mysql
  encoding: utf8
  database: demo_production
  username: demouser#<-- MAKE UP A NON "root" USER
  password: demopswd # <-- MAKE UP ANY PASSWORD (can't be empty)
  hostname: db_primary
  #socket: /tmp/mysql.sock <-- YOU CAN REMOVE THIS LINE

Run the EC2 on Rails Capistrano Tasks

Hack to deal w/ Capistrano limitation:

cap ec2onrails:get_public_key_from_server
cap ec2onrails:server:set_roles

Configure the db and stuff:

cap ec2onrails:setup

And launch your app:

cap deploy:cold

Boom! You should be running …

Problems? Check the docs at EC2 on Rails and their Google Group.

Thanks to Paul Dowman for EC2 on Rails!