Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save RodCyb3Dev/929d94c5f095d6db5d6ac25626a4f548 to your computer and use it in GitHub Desktop.

Select an option

Save RodCyb3Dev/929d94c5f095d6db5d6ac25626a4f548 to your computer and use it in GitHub Desktop.
Complete guide for deploying rails application to aws ec2 instance, using capistrano as deploying tool with nginx & puma server

Deploy Rails Application to AWS EC2

Creating AWS EC2 Instance

- login to 'AWS Management Console' (https://aws.amazon.com/console/)
- from 'Services'(in navbar) choose 'EC2'
- from 'Create Instance' section, click on 'Launch Instance'
- then select 'AMI' (Amazon Machine Image), we will be using 'Ubuntu Server 16.04 LTS (HVM)' as example
- select 'Instance Type' as per your requirement
- then click 'Next:Configure Instance Details' to continue
  change 'Configure Instance Details' or used as default settings
- click 'Next: Add Storage'
  adjust size as per your need (default is 8GB)
- click 'Next: Tag Instance'
  create tag if you need any tagging for your instance
- click 'Next: Configure Security Group'
  click 'Add Rule' to add new rule(for port, ip address etc.)
  default you can set it to -
  SSH      TCP     22     Anywhere     0.0.0.0/0
  HTTP     TCP     80     Anywhere     0.0.0.0/0 
- then click 'Review and Launch'
  check all your setting, then click 'Launch'
- select existing or create new keypair to connect to your instance
  click 'Launch Instance', this will generate the key (in case of new keypair) & launches your instance
  find 'Public IP' from 'Description'

Setup Elastic IP

- you can generate an Elastic IP from 'Network & Security' tab
- click 'Allocate new address'
- then click 'Allocate', this will generate an Elastic IP
- click 'Close', this will redirect you to Elastic IP Dashboard
- select you Elastic IP & on right click select 'Associate address'
- choose you instance (whom you want to associate) & click 'Associate'
  this will replace your Public IP with Elastic IP (& now this IP is used)

Setup the server to connect

#login to your server from terminal using pem file (generated private key)
- ssh -i "<Path of your pem file>" ubuntu@<Public IP Address>
- sudo apt-get update && sudo apt-get -y upgrade #to update existing packages
- create 'deploy' user for deploying the application to server
- sudo useradd -d /home/deploy -m deploy #the application will be deployed in /home/deploy directory
- sudo passwd deploy #set the password for 'deploy' user
- run 'sudo visudo' & add 'deploy ALL=(ALL:ALL) ALL' into the file & save

Generating ssh-key

- su - deploy
- ssh-keygen #do not set a passphrase for the key
- cat .ssh/id_rsa.pub
- copy the ssh-key & set it as your deploy key on your repository(project on bitbucket or github)
- copy your system public ssh-key & paste it into the following file on your instance as deploy user
  nano .ssh/authorized_keys #save & exit

Installing GIT

- sudo apt-get install git

Installing Nginx

- sudo apt-get install nginx
- sudo nano /etc/nginx/sites-available/default #to configure default site
#add this content to file
upstream app {
  # Path to Puma SOCK file, as defined previously
  server unix:/home/deploy/<application name>/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  listen 80;
  server_name localhost;

  root /home/deploy/<application name>/public;

  try_files $uri/index.html $uri @app;

  location / {
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Connection '';
    proxy_pass http://app;
  }

  location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

Installing ruby

- su - deploy
- gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
- \curl -sSL https://get.rvm.io | bash -s stable
- rvm install ruby #you can specify required ruby version
- rvm use ruby
- gem install bundler #install bundler

Create files required by capistrano

- mkdir <application name>
- mkdir -p <application name>/shared/config
- nano <application name>/shared/config/database.yml
#for rails 5.2 'master.key' file is used for secret key
#for rails lower versions 'application.yml' or 'secrets.yml' is used for secret key
- nano <application name>/shared/config/application.yml #change application.yml file name as per you required
- add this to it #you can add master.key for rails 5.2
SECRET_KEY_BASE: "8a2ff74119cb2b8f14a85dd6e213fa24d8540fc34dcaa7ef8a35c246ae452bfa8702767d19086461ac911e1435481c22663fbd65c97f21f6a91b3fce7687ce63"

Rails application setup for capistrano

#configuring capistrano
#add this to gemfile
group :development do
  gem 'capistrano'
  gem 'capistrano3-puma'
  gem 'capistrano-rails', require: false
  gem 'capistrano-bundler', require: false
  gem 'capistrano-rvm'
end
- bundle install

#create configuration files for capistrano
- config/deploy.rb
- config/deploy/production.rb

#add these line to capfile
require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/rails/assets' # for asset handling add
require 'capistrano/rails/migrations' # for running migrations
require 'capistrano/puma'

edit deploy.rb

lock '3.4.0'

set :application, 'contactbook'
set :repo_url, '<git application path>' # Edit this to match your repository
set :branch, :master
set :deploy_to, '/home/deploy/<application name>'
set :pty, true
set :linked_files, %w{config/database.yml config/application.yml}
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/uploads}
set :keep_releases, 5
set :rvm_type, :user
set :rvm_ruby_version, 'jruby-1.7.19' # Edit this if you are using MRI Ruby

set :puma_rackup, -> { File.join(current_path, 'config.ru') }
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"    #accept array for multi-bind
set :puma_conf, "#{shared_path}/puma.rb"
set :puma_access_log, "#{shared_path}/log/puma_error.log"
set :puma_error_log, "#{shared_path}/log/puma_access.log"
set :puma_role, :app
set :puma_env, fetch(:rack_env, fetch(:rails_env, 'production'))
set :puma_threads, [0, 8]
set :puma_workers, 0
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :puma_preload_app, false

Edit the config/deploy/production.rb

server '<server public IP address>', user: 'deploy', roles: %w{web app db}

Deploy code to AWS

cap production deploy
#login to server & finally restart the nginx
sudo service nginx restart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment