git svn clone of rubber. Perhaps some contribs if needed
Switch branches/tags
Nothing to show
Latest commit 400d46c Apr 5, 2008 wr0ngway wr0ngway ignores
git-svn-id: 04602977-1bcd-48be-894b-5e2845e2d00e


The rubber plugin enables relatively complex multi-instance deployments to
Amazon's Elastic Compute Cloud (EC2).

If you just want a simple single instance setup for your rails app, you might
be better off using something like ec2onrails (which I borrowed heavily from).
The main difference between the two is that rubber was built from the
ground-up to support deploying to multiple instances, and has a very flexible
mechanism for configuring said instances at a host, role or global level.
That is, you can define a set of configuration files for a role, thereby making
it easy to create as many instance for that role as you desire (e.g. scaling up
the quantity of instances you need to host your app servers)


* An EC2 account with keypair (both public and private keys) and port 22 access
    to the default security group (ec2-authorize default -p 22)
    See the EC2 docs for more details:
* amazon-ec2: gem install amazon-ec2
* Capistrano: gem install capistrano


First, Rubber needs to be installed as a rails plugin.  Then run its
vulcanize generator to add a basic set of configuration files to your

Edit config/rubber/rubber.yml to add your settings.  You can edit or
add to the config files in RAILS_ROOT/config/rubber/<common|role|host> to
setup instances globally or for specific roles and/or hosts.

You will also need to customize config/deploy.rb for your needs

You probably don't want to do this, but running "rake rubber:config" in a
development env will tranform config files for the global scope along with
the config file for all roles, and config files for the current machine
(if any), but not config files specific to other hosts.  This helps one to
test out config file transformations before committing and deploying to your
instances.  Currently this needs to run via sudo as it typically writes to
files that only root can modify (e.g./etc/my/my.cnf) - I need  a better
solution here, maybe writing them to a "Fake root" in /tmp.

See RUNNING below for a walkthrough on installing rubber for a demo rails app.


Config files are just ERB templates.  There are some special variables that
need to be set at the top of the config template file that control what
happens when the template is transformed:

@path       The output path to write the transformed config file to
@read_cmd   The command to use for reading the original config file from
            e.g. "crontab -l"
@write_cmd  The command to use for piping the transformed config file to
            e.g. "crontab -"
@post       The command to run after generating the config file ONLY if it
            has changed
@owner      The owner the output file should have, e.g. "root"
@group      The group the output file should have, e.g. "system"
@perms      The permissions the output file should have, e.g. 644
@additive   Sets transformation to be additive, only replaces between given
            delimiters, e.g. @additive = ["## start", "## end"]

Of the above, the only variables that are required are  @path or both
@read_cmd and @write_cmd

In addition, within the config templates you have access to the rubber
configuration objects rubber_env (rubber.yml) and rubber_instances
(instance*.yml).  This makes it possible to write config files in such a way
that adding more instances gets handled automatically - e.g. the proxy
destinations in the nginx.conf need to get updated when we add more app server

Configuration files that exist in config/rubber/common will be transformed for
all hosts.
Configuration files that exist in config/rubber/role/<role_name> will only be
transformed on the hosts that are members of role_name.
Configuration files that exist in config/rubber/host/<host_name> will only be
transformed on the hosts with a hostname of host_name.


Once rubber is installed and configured for your project, the workflow
is as follows:

Create instance(s)
Bootstrap instance(s)
cap deploy(:cold)
Rinse, Repeat

Since bootstrap runs for all roles/hosts, not just the newly created ones, I
tried to make it safe for repeat executions on existing instances.  However,
you should probably verify that this is the case for your setup before
trusting it on a production system.

Note that if you change a config file template, you need to check it in before
rubber:config will be able to see the change on remote hosts.  However,
changing rubber.yml or instance*.yml do not need to be checked in for their
changes to be seen remotely because they are pushed by the rubber:config

For example, you can follow these steps to create a demo app on a single

Create a simple rails project:
rails rubbertest
cd rubbertest
./script/generate scaffold post title:string body:text

Install rubber:
./script/plugin install
./script/generate vulcanize minimal_mysql

Configure rubber:
<edit config/rubber/rubber.yml>
For demo, you need real values for these:
You should go through the rest for a real app.

Create, bootstrap, then deploy to instance:
ALIAS=www ROLES=web,app,db:primary=true cap rubber:create
cap rubber:bootstrap
cap deploy:setup
cap deploy:cold

or for a more complex production setup

ALIAS=web01 ROLES=web cap rubber:create
ALIAS=app01 ROLES=app cap rubber:create
ALIAS=app02 ROLES=app cap rubber:create
ALIAS=db01 ROLES=db:primary=true cap rubber:create
ALIAS=db02 ROLES=db cap rubber:create
cap rubber:bootstrap
cap deploy:setup
cap deploy:cold

To add another app server:

ALIAS=app03 ROLES=app cap rubber:create
cap rubber:bootstrap
cap deploy


To add some custom install steps in your deploy.rb:

after "rubber:install_packages", "custom_install"

task :custom_install do
  # Setup ssh access to svn from all hosts
  svn_pvt_key = <<-DATA
    -----END DSA PRIVATE KEY-----
  svn_pvt_key.gsub!(/^ */, '')
  svn_pub_key = "ssh-dss YYY"
  put(svn_pvt_key, "/root/.ssh/id_dsa", :mode => 0600)
  put(svn_pub_key, "/root/.ssh/", :mode => 0600)

  # Get host key for src machine to prevent ssh from failing
  # during cap deploy
  run "ssh  -o 'StrictHostKeyChecking=no' echo"

task :custom_install_app, :roles => :app do
  # add the rails user for running app server with
  run "adduser --system --group rails"

If anyone has any configuration templates similar to what is provided in
generators/vulcanize/templates, please contribute them to
the project.


Matt Conway