I work a lot with EC2 and one thing I always have to Google is how to SSH into an AMI, Ubuntu, Fedora, or CentOS instance. Part of the challenge is that the usernames slightly differ so I wrote this Rakefile to help me remember how to complete simple tasks.

If you're unfamiliar with Rake Tasks, try reading this first.

I picked up Rake Tasks while working on Ruby on Rails projects but nowadays I use it as shell script replacement. What I particularly like about Tasks are that you can organize them by grouping them into namespaces.

Tasks and namespaces enable me to only have to mange one ~/Desktop/Rakefile per project instead of dozens of .shell scripts
or shell aliases.

Example of my Rakefile.

namespace :aws do
  desc %Q{ ›› SSH into an EC2 instance. rake aws:ssh[pem,ami,] }
  task :ssh, [:pem, :os, :ip] do |task, args|
    aws_pem       = args.pem
    aws_user      = user(args.os)
    aws_ip_or_url = args.ip
    sh %{ ssh -i #{aws_pem} #{aws_user}@#{aws_ip_or_url} }
  desc %Q{ ›› SCP files to EC2 Instance. }
  task :upload, [:pem, :os, :ip, :local, :dest] do |task, args|
    assets_dir    = args.local || "/path/to/local/files/you/want/to/upload/*"
    aws_pem       = args.pem
    aws_user      = user(args.os)        
    aws_ip_or_url = args.ip
    aws_dir       = args.dest  || "/path/to/destination/directory"
    sh %{ scp -i #{aws_pem} #{assets_dir} #{aws_user}@#{aws_ip_or_url}:#{aws_dir} }
  desc %Q{ ›› Fix PEM permissions. }
  task :fix_pem, [:pem] do |task, args|
    aws_pem = args.pem || "/path/to/aws/file.pem"
    sh %{ chmod -R 600 #{aws_pem} }
  desc %Q{ ›› Get External IP }
  task :external_ip do
    sh %{ curl -s http://checkip.dyndns.org/ | sed 's/[a-zA-Z<>/ :]//g' }


def user(os)
  user = case os
  when "ubuntu" then "ubuntu"
  when "ams"    then "amsadmin"
  when "fms"    then "fmsadmin"
  when "ami"    then "ec2-user"
  when "debian" then "admin"
  when "redhat" then "ec2-user"
  when "fedora" then "fedora"
  when "centos" then "centos"
  when "bitnami" then "bitnami"
  when "freebsd" then "ec2-user"
  else "ec2-user"
  return user

This enables me to then open up Terminal and run:

 rake aws:ssh[/path/to/private.pem,ubuntu,55.XX.XX.XX]

If the EC2 instance I pick is a bitnami instance, then I only need to change the os parameter to "bitnami".

 rake aws:ssh[/path/to/private.pem,bitnami,55.XX.XX.XX]

If I later want to upload a batch of files to a specific directory on a Debian instance, then script is still simple:

rake aws:upload[/path/to/private.pem,debian,ec2-XX-XXX-XX-XX.compute-1.amazonaws.com,/path/to/local/files,/path/to/destination/directory]

If I want to check what's my IP address on my local computer:

rake aws:external_ip

How is this Better?

Simple, I have the power of Java ANT with all the simplicity of Ruby.

If I type this command:

rake -T

All of my scripts are neatly organized and available to pass to another developer in your team.


Rake Tasks for Mac OS X

I also use Rake Tasks for simple Mac OS X commands. Read Now.

Rake Tasks for Node Developers

If you prefer an all Javascript environment, I have a tutorial on how to create Tasks using Node.