Bootstrapping a ‘deploy’ user with Capistrano on EC2

Amazon’s EC2 is rightly so the best thing since sliced bread. All of our hosted services at Vamosa run off EC2. Getting our Ubuntu instances provisioned these days is easily achieved using Capistrano, but when we were still get familiar with ‘cap’ it wasn’t always the case.

Amazon EC2 uses private/public keys files for root user authentication but you want to use those credentials as infrequently as possible. As RubyOnRails users, we are used to setting up a deploy user which we use to run Apache 2 and Phusion Passenger under. We use that same deploy user to connect to our github repositories and pull in code updates. All pretty much standard stuff.

When we using off-the-shelf Ubuntu 8.0.4 AMIs we couldn’t find any nice Capistrano recipes to setup that initial deploy user and enabling key-based login to that deploy user using our own personal keys.

The following recipe does just that:

1
2
3
4
5
6
7
8
9
10
11
12
13
  desc "uploads id_rsa.pub to the EC2 instance's deploy users authorized_keys2 file"
  task :bootstrap_deploy_user do
    system "ssh -i #{aws_private_key_path} root@#{domain} \"groupadd admin\""
    system "ssh -i #{aws_private_key_path} root@#{domain} \"useradd -d /home/#{user} -s /bin/bash -m #{user}\""
    system "ssh -i #{aws_private_key_path} root@#{domain} \"echo #{user}:#{password} | chpasswd\""
    system "ssh -i #{aws_private_key_path} root@#{domain} \"usermod -a -G admin deploy\""
    system "ssh -i #{aws_private_key_path} root@#{domain} \"mkdir /home/#{user}/.ssh\""
    for key in ssh_options[:keys]
      system "cat  #{key}.pub | ssh -i #{aws_private_key_path} root@#{domain} \"cat >> /home/#{user}/.ssh/authorized_keys2\""
    end
    system "ssh -i #{aws_private_key_path} root@#{domain} \"chown -R #{user}:#{user} /home/#{user}/.ssh\""
    system "scp -i #{aws_private_key_path} config/deploy_sudoers root@#{domain}:/etc/sudoers"
  end

You’ll need to setup Capistrano variables as you can see to make this work. My .caprc file contains the following definition:

set :aws_private_key_path, "/Users/ijonas/.ec2/ec2keypair.pem"

Our config/deploy.rb contains the following variables:

set :use_sudo, false
set :user, 'deploy'
set :password, 'xxxxx'
set :application, "yyyyy.vamosa.com"
set :domain, "yyyyy.vamosa.com"
set :deploy_to, "/var/www/apps/#{application}"

The approach is a little bit ‘hackish’ but it works for EC2, and keeps your Capistrano setup as close as possible to the best-practice.



Leave a Reply