Monday, November 25, 2013

Deploy Rails application from Github to AWS EC2 using Capistrano 3


1. EC2 Instance
2. GitHub account with some code
3. Confirm SSH has been enabled on this instance
4. Connecting to a EC2 Instance

How to grant access to multiple developers to EC2 instance

  • Ask a developer who already has access to the machine to add your public key to authorized keyscat ~/somefolder/ | ssh @ "cat >> ~/.ssh/authorized_keys"
  • Developer public key can be downloaded from github curl -O

Setup (for a new instance)

  • Use Amazon Linux AMI 2013.09.1 - Amazon Machine Image (AMI) - 64 bit
  • Open SSH and TCP Ports (while setting up instance, or it can be done later too)
  • Add your public key to authorized keys so that you don't have to use the private key each timecat ~/.ssh/ | ssh -i ec2-user@ "cat >> ~/.ssh/authorized_keys"
  • Install Ruby 2.0 and Rails 4.0 - make sure Ruby is installed with openssl, donot install rvm and ruby as root user
  • Confirm Ruby has been installed with OpenSSL ruby -ropenssl -e "puts OpenSSL::VERSION"
  • Configure SSH Agent forwarding for capistrano - Agent forwarding should work out of the box, just make sure to add your keys to the agent using ssh-add
    1. Verify that git connection using ssh-agent is working cap staging git:check
    2. Troubleshooting
  • Provision server to deploy servers list using capistrano
    1. Edit staging.rb/production.rb and change/add new machine
    2. Create folder with its role in home dir $mkdir staging or mkdir production 
  • Deploy to staging cap staging deploy

  • Capistrano Deploy Scripts


    set :application, 'app name'
    set :repo_url, ''
    set :rvm_type, :user

    namespace :deploy do

      desc "Start unicorn"
      task :start do
        on roles(:app), in: :sequence, wait: 5 do
          within current_path do
            with rails_env: fetch(:stage) do
              execute :bundle, "exec unicorn_rails -c config/unicorn.rb -D"

      desc "Stop unicorn"
      task :stop do
        on roles(:app), in: :sequence, wait: 5 do
          execute "kill -s QUIT `cat #{shared_path}/`" if test("[ -f #{shared_path}/ ]")

      desc 'Restart unicorn'
      task :restart do
        on roles(:app), in: :sequence, wait: 5 do
          # this is a bad way to invoking, but spent 3 hrs searching for this

      before 'deploy:start', 'rvm:hook'

      after :finishing, 'deploy:cleanup'



    set :stage, :staging

    server '', user: 'ec2-user', roles: %w{app}

    set :branch, 'develop'

    set :deploy_to, '/home/ec2-user/staging'