Monday, October 6

Bootstrapping GitHub Access on a Fresh EC2 Instance

If you'll recall from my last post, I've spent an extended weekend getting a mature Rails application running on Amazon's Elastic Computing Cloud (EC2). Yes, I took two vacation days off work (where I suffer with Java and ATG) to spend some quality time with Rails and EC2, and more accurately Capistrano.

My short-term goal was to get the application running (which I did), then to automate deployment. Since EC2 affords you the luxury of conjuring up fresh severs on a whim, I wanted to make sure I had a simple single Capistrano task that could take a virgin machine and impregnate it with my application. (Wow, that metaphor kinda strayed into the inappropriate zone, eh?)

Out of the box, the EC2 on Rails gem gives you some handy recipes for setting up a fresh instance and deploying to it, but it misses a couple little chicken-and-egg bootstrapping niggles. One of those is GitHub access.

In order to pull your repository off GitHub, you have to have your SSH keys set up. This is generally a manual and slightly tedious process. The GitHub guides do an excellent job of walking you through it. However, I don't want to run through that rigamarole every time I christen a new server; I want that chore to be automated.

This certainly isn't the most elegant way to solve it, and I don't recommend it for a long-term large-scale operation, but here's how I handled it...

I generated the SSH keys on a single machine then copied the "id_rsa" and "id_rsa.pub" files into my "config/deploy" folder. So I now have a copy of the super secret files necessary for accessing my remote repository in the repository itself. I'm aware of how dumb this is from a security perspective, and you should be too, so just put down the flamethrower and back away from the keyboard. I'm keeping things simple and practical here; this isn't the source code for an electronic voting machine after all.

Next I created a Capistrano recipe to copy the SSH key files from my "config/deploy" directory up to the target server (being deployed to) into its "~/.ssh" directory (where the remote ssh command expects to find them). Note that this puts the same keys on every server.

namespace :spumco do
namespace :ec2 do
desc "copy the GitHub keys"
task :copy_github_keys do
upload "config/deploy/id_rsa", "~/.ssh", :via => :scp
upload "config/deploy/id_rsa.pub", "~/.ssh", :via => :scp
end
end
end

I then used the "after" hook to ensure this recipe runs after the EC2 on Rails gem completes its native "setup" recipe.

after "ec2onrails:setup", "spumco:ec2:copy_github_keys"

Now every time I create a brand-spanking-new instance on EC2 and I run the "cap ec2onrails:setup" command it does everything it needs to do to prepare that server for receiving the only other command that needs to be run, "cap deploy".

1 comment:

jpb said...

So why not just have cap copy the ssh keys from a known path in your homedir instead of from the repo?

Then you don't have to have them lying around in your repository.