Deploy to EC2 with Rubber on Rails 3

Rubber is a gem which makes it easy to make multi-instance deployments of your rails app to EC2. It uses capistrano to do this.

Before proceeding, make sure you have your EC2 account created and have a keypair set up with Amazon.

Here is recipe of what I’ve done so far. I’m running into issues as I describe below. You may not run into them. If you do, please let me know if you were able to work around these issues.

The following instructions assume you use Rails 3 and Ruby 1.9.2. The instructions on the Rubber Github page, are slightly different since they use Rails 2.x.

Do the following on your own personal machine. You will use the cap rubber:create_staging command to deploy to EC2.

rvm use 1.9.2
gem install capistrano --no-rdoc
rails new rubbertest
cd rubbertest
gem install rubber --no-rdoc
bundle install
rails generate scaffold post title:string body:text
rails generate vulcanize complete_passenger_mysql
rake db:migrate
set .rvmrc file to include: rvm use 1.9.2@rails3

Then configure your rubbertest/config/rubber/rubber.yml file. Modify your app_name, app_user, domain, access_key, secret_access_key, account. I made some assumptions and set my configuration to the following:

app_name: rubbertest
app_user: ec2-user
domain: yourdomainname.com (I just assigned a temporary domain even though it may have not been necessary? Not sure)
access_key: (set it to yours)
secret_access_key: (set it to yours)
account: (set it to your account number)

I haven’t yet found a clear explanation on what to set some of the fields above. So unfortunately, I’m taking some guesses with some of them right now. I will update as soon as I figure this out. If you can explain each, please comment and help other RoRists accelerate their learning.

Here is the issue I’m running into when executing the cap rubber:create_staging which is supposed to deploy my rubbertest app onto EC2:

btw… once you type cap rubber:create_staging, just accept the defaults by pressing enter.

navid@~/Development/rubbertest: <strong>cap rubber:create_staging</strong>
    triggering load callbacks
  * executing `rubber:init'
  * executing `rubber:create_staging'
Hostname to use for staging instance [production]: 
Roles to use for staging instance [web,app,db:primary=true]: 
  * executing `rubber:create'
/Users/navid/.rvm/rubies/ruby-1.9.2-preview3/lib/ruby/1.9.1/openssl/digest.rb:55:in `initialize': <strong>Unsupported digest algorithm (sha256). (RuntimeError)</strong>
	from /Users/navid/.rvm/rubies/ruby-1.9.2-preview3/lib/ruby/1.9.1/openssl/digest.rb:55:in `initialize'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:96:in `new'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:96:in `encode'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:310:in `get_aws_auth_param'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:286:in `block in make_request'
	from /Users/navid/.rvm/rubies/ruby-1.9.2-preview3/lib/ruby/1.9.1/net/http.rb:627:in `start'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:274:in `make_request'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:324:in `response_generator'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS/EC2/security_groups.rb:42:in `describe_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/cloud/aws.rb:93:in `describe_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/security_groups.rb:102:in `sync_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/security_groups.rb:51:in `setup_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/instances.rb:193:in `create_instance'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/instances.rb:38:in `block (2 levels) in load'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `instance_eval'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `invoke_task_directly'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/callbacks.rb:27:in `invoke_task_directly_with_callbacks'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:89:in `execute_task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/namespaces.rb:186:in `method_missing'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/namespaces.rb:104:in `block in task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/utils.rb:22:in `block (2 levels) in load'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `instance_eval'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `invoke_task_directly'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/callbacks.rb:27:in `invoke_task_directly_with_callbacks'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:89:in `execute_task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:101:in `find_and_execute_task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:46:in `block in execute_requested_actions'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:45:in `each'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:45:in `execute_requested_actions'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/help.rb:19:in `execute_requested_actions_with_help'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:34:in `execute!'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:14:in `execute'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/bin/cap:4:in `<top (required)>'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/bin/cap:19:in `load'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/bin/cap:19:in `<main>'

First of all, don’t be alarmed that I’m using ruby-1.9.2-preview instead of ruby-1.9.2-p0 or whatever it was. I was hoping that I would get rid of the issue above if I upgraded my ruby version but unfortunately I get the same error.

I went into the digest.rb file as mentioned in stack trace and printed the openssl version. It was an older version which I don’t believe supports sha256? It made me realize that it’s probably using a version of openssl that’s tied to the ruby rvm version and it’s not using the openssl from my system. I did a puts to stdout from within the digest.rb and it was older.

The only way I was able to get around this problem was to hack AWS.rb:96 (mentioned in stack trace above) and set it to use sha1 instead of sha256 (changed digest = OpenSSL::Digest::Digest.new(‘sha256’) to digest = OpenSSL::Digest::Digest.new(‘sha1’)
See Rubber on Github and Rubber’s Wiki

Once I did that, I got past that point and ran into issues with keys/authentication, which seems like I’m very close!

However, I get a new error below:

navid@~/Development/rubbertest: <strong>cap rubber:create_staging</strong>
    triggering load callbacks
  * executing `rubber:init'
  * executing `rubber:create_staging'
Hostname to use for staging instance [production]: 
Roles to use for staging instance [web,app,db:primary=true]: 
  * executing `rubber:create'
/Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:363:in `aws_error?': <strong>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. (AWS::SignatureDoesNotMatch)</strong>
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:300:in `block in make_request'
	from /Users/navid/.rvm/rubies/ruby-1.9.2-preview3/lib/ruby/1.9.1/net/http.rb:627:in `start'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:274:in `make_request'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS.rb:324:in `response_generator'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/amazon-ec2-0.9.17/lib/AWS/EC2/security_groups.rb:42:in `describe_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/cloud/aws.rb:93:in `describe_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/security_groups.rb:102:in `sync_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/security_groups.rb:51:in `setup_security_groups'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/instances.rb:193:in `create_instance'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/instances.rb:38:in `block (2 levels) in load'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `instance_eval'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `invoke_task_directly'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/callbacks.rb:27:in `invoke_task_directly_with_callbacks'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:89:in `execute_task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/namespaces.rb:186:in `method_missing'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/namespaces.rb:104:in `block in task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/rubber-1.8.0/lib/rubber/recipes/rubber/utils.rb:22:in `block (2 levels) in load'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `instance_eval'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:139:in `invoke_task_directly'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/callbacks.rb:27:in `invoke_task_directly_with_callbacks'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:89:in `execute_task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/configuration/execution.rb:101:in `find_and_execute_task'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:46:in `block in execute_requested_actions'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:45:in `each'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:45:in `execute_requested_actions'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/help.rb:19:in `execute_requested_actions_with_help'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:34:in `execute!'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/lib/capistrano/cli/execute.rb:14:in `execute'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/gems/capistrano-2.5.19/bin/cap:4:in `<top (required)>'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/bin/cap:19:in `load'
	from /Users/navid/.rvm/gems/ruby-1.9.2-preview3/bin/cap:19:in `<main>'

Even after I tried to upgrade openssl on my mac, I still see "Unsupported digest algorithm"

navid@~/Development/rubbertest: sudo port install openssl
Password:
--->  Computing dependencies for openssl
--->  Fetching openssl
--->  Attempting to fetch openssl-1.0.0c.tar.gz from http://distfiles.macports.org/openssl
--->  Verifying checksum(s) for openssl
--->  Extracting openssl
--->  Applying patches to openssl
--->  Configuring openssl
--->  Building openssl
--->  Staging openssl into destroot
--->  Installing openssl @1.0.0c_0
--->  Deactivating openssl @1.0.0a_1
--->  Activating openssl @1.0.0c_0
--->  Cleaning openssl
navid@~/Development/rubbertest: openssl version
OpenSSL 1.0.0c 2 Dec 2010
navid@~/Development/rubbertest: rvm exec ruby -v -ropenssl -e "p OpenSSL::Digest.new('sha256')"
ruby 1.9.2p0 (2010-08-18 revision 29036) [i386-darwin9.8.0]
-e:1:in `initialize': Unsupported digest algorithm (sha256). (RuntimeError)
	from -e:1:in `new'
	from -e:1:in `<main>'
ruby 1.9.2dev (2010-05-31 revision 28117) [i386-darwin9.8.0]
-e:1:in `initialize': Unsupported digest algorithm (sha256). (RuntimeError)
	from -e:1:in `new'
	from -e:1:in `<main>'

However, I was finally able to get rid of this problem by doing the following. You may not need to upgrade to Snow Leopard from Leopard but I went ahead. I thought I would be able to get rid of this problem easily by upgrading to Snow Leopard, which I later proved to be false assumption. After I upgraded to Snow Leopard, I had a huge set of other problems I had to deal with which included having to reinstall Macports, install the latest version of Xcode and install libxml2 and sqlite via source and then rebuild rvm for 64 bit instead of i386 (32-bit).

Here is some of the things I tried:

Download the tarball of openssl from http://openssl.org/ instead of just doing a port install openssl.
Then do the following:

tar xvfz openssl-x.x.x.tar.gz
cd openssl-x.x.x
./configure
make
sudo make install

I also installed sqlite via source as well by downloading it from http://www.sqlite.org/download.html and doing:

tar xvfz sqlite-amalgamation-3.6.23.1.tar.gz
cd sqlite-autoconf-3070400
./configure --disable-dependency-tracking
make
sudo make install

I then uninstalled all rubies (rvm ruby instances) one by one. There may be an argument which will uninstall all rubies in one go? I didn’t bother since I only had 3 instances to delete:

rvm list
rvm uninstall ruby-1.9.2-head (for example)

I then reinstalled ruby-1.9.2-head and compiled in 64-bit. You may not need to pass the same flags but I had to since it would complain similar to the following:

tcltklib.c:9539: warning: implicit conversion shortens 64-bit value into a 32-bit value
ld: in /usr/local/lib/libsqlite3.dylib, file was built for i386 which is not the architecture being linked (x86_64)
collect2: ld returned 1 exit status
make[1]: *** [../../.ext/x86_64-darwin10/tcltklib.bundle] Error 1
make: *** [mkmain.sh] Error 1

So, I did the following to install ruby-1.9.2-head:

rvm install 1.9.2-head -C --enable-shared,--with-readline-dir=/opt/local,--build=x86_64-apple-darwin10
VN:F [1.9.22_1171]
Rating: 5.0/5 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)
Deploy to EC2 with Rubber on Rails 3, 5.0 out of 5 based on 2 ratings
Facebook Twitter Email

2 Comments to “Deploy to EC2 with Rubber on Rails 3”