Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Latest commit 400d46c
Apr 5, 2008
git-svn-id: http://rubber.rubyforge.org/svn/trunk@111 04602977-1bcd-48be-894b-5e2845e2d00e
|Failed to load latest commit information.|
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) REQUIREMENTS: * 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: http://docs.amazonwebservices.com/AWSEC2/2007-08-29/GettingStartedGuide/?ref=get-started * amazon-ec2: gem install amazon-ec2 * Capistrano: gem install capistrano INSTALLATION: 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 project. 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. CONFIGURATION: 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 instances. 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. RUNNING: 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 recipe. For example, you can follow these steps to create a demo app on a single instance: Create a simple rails project: rails rubbertest cd rubbertest ./script/generate scaffold post title:string body:text Install rubber: ./script/plugin install http://rubber.rubyforge.org/svn/trunk ./script/generate vulcanize minimal_mysql Configure rubber: <edit config/rubber/rubber.yml> For demo, you need real values for these: aws_access_key aws_secret_access_key ec2_key_name ec2_key_file 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 EXTEND: 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 -----BEGIN DSA PRIVATE KEY----- XXXX -----END DSA PRIVATE KEY----- DATA svn_pvt_key.gsub!(/^ */, '') svn_pub_key = "ssh-dss YYY firstname.lastname@example.org" put(svn_pvt_key, "/root/.ssh/id_dsa", :mode => 0600) put(svn_pub_key, "/root/.ssh/id_dsa.pub", :mode => 0600) # Get host key for src machine to prevent ssh from failing # during cap deploy run "ssh -o 'StrictHostKeyChecking=no' email@example.com echo" custom_install_app end task :custom_install_app, :roles => :app do # add the rails user for running app server with run "adduser --system --group rails" end If anyone has any configuration templates similar to what is provided in generators/vulcanize/templates, please contribute them to the project. Enjoy! Matt Conway