Monday, November 25, 2013

Deploy Rails application from Github to AWS EC2 using Capistrano 3


Prerequisites


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/developer_to_be_added_id_rsa.pub | ssh @ "cat >> ~/.ssh/authorized_keys"
  • Developer public key can be downloaded from github curl -O https://github.com/.keys

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/id_rsa.pub | 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

    #####deploy.rb#######

    set :application, 'app name'
    set :repo_url, 'git@github.com:/.git'
    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"
            end
          end
        end
      end

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

      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
          Rake::Task["deploy:stop"].invoke
          Rake::Task["deploy:start"].invoke
        end  
      end

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

      after :finishing, 'deploy:cleanup'

    end

    #####staging.rb#######

    set :stage, :staging

    server 'ec2-hostname.amazonaws.com', user: 'ec2-user', roles: %w{app}

    set :branch, 'develop'

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

    1 comment: