Deploy rails application to AWS
How to deploy Rails application on AWS EC2 + Ubuntu + Nginx + Capistrano
September 22, 2020 • 6 min read • AWS
Deplyment is moving your code from local machine to the server to make your application accessible by end-users. in this article we will go through all the process from setting the instance, dependencies, to deploying the code using the Capistrano tool
Set up EC2 Ubuntu:
Note: if you already configured the instance, please jump to the next step
First of all, we will need a valid AWS account to setup the instance. if you already have an account, please Sign in otherwise, create a new one Create an AWS account
Assuming you have created an AWS account let's login to our console and set up the instance
- Step 1: Select the first one
-
Step 2: go to instances and select launch instance
-
Step 3: Choose an Amazon Machine Image (AMI) in our case we will choose
Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
and complete the rest of the steps and coonect to the server via sshssh -p 22 -i ~/.ssh/[YOUR_KEY] ubuntu@[YOUR_IP_ADDRESS]
.
- ** nstalling dependencies**
Having a vanilla server like having a new PC with OS which will need from you to install the dependencies of your stack. If your Ruby on rails developer you will need to install RVM, Ruby, pg, MySQL, etc or if your front end developer you will need to install front end dependencies like node, npm, yarn, and etc.
In our case, we will need to install Nginx, PG (If your using MySQL install the MySql engine)
, RVM, Redis (If your planning to use Background jobs)
1) ngix + required packages
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install curl git-core nginx build-essential tcl8.5 -y
2) DB engine
install your DB engine pg
or Mysql
- PostgresQL -
sudo apt-get install libpq-dev postgresql postgresql-contrib
- MySql -
sudo apt-get install libmysqlclient-dev mysql-server
2) Redis
Note: if you're not using any Back-ground jobs in your application like Resque or sidekiq pls skip this step
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes with radius queries and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster
cd ~
wget http://download.redis.io/releases/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
make test
sudo make install
cd utils
sudo ./install_server.sh
3) RVM
RVM is a command-line tool which allows you to easily install, manage, and work with multiple ruby environments from interpreters to sets of gems.
- Install GPG keys:
gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
- Install RVM and Ruby
curl -sSL https://get.rvm.io | bash -s stable
source ~/.rvm/scripts/rvm
rvm requirements
rvm install 2.7.1
rvm use 2.7.1 --default
- Auto update rvm
echo rvm_autoupdate_flag=2 >> ~/.rvmrc
- install
rails, bundler, (mysql2or pg) gems
gem install rails -V --no-ri --no-rdoc
gem install bundler -V --no-ri --no-rdoc
gem install mysql2 -v '0.4.3'
gem install pg -v '1.0.0'
4) Generate ssh key
Ssh-keygen is a tool for creating new authentication key pairs for SSH. Such key pairs are used for automating logins, single sign-on, and for authenticating hosts.
- Generate new one
ssh-keygen -t rsa
- Print generated key
cat ~/.ssh/id_rsa.pub
Before we go to the next step please check if everything is installed perfectly in the previous steps, if it's not please re-check and install again
~$ nginx -v
# nginx version: nginx/1.14.0 (Ubuntu)
~$ rails -v
# Rails 5.2.2
~$ bundler -v
# Bundler version 2.0.1
~$ mysqld --version
# mysqld Ver 5.7.31-0ubuntu0.18.04.1 for Linux on x86_64 ((Ubuntu))
~$ psql --version
# psql (PostgreSQL) 12.3 (Ubuntu 12.3-1.pgdg18.04+1)
~$ redis-server --version
# Redis server v=4.0.9 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=9435c3c2879311f3
Configuring rails with Capistrano
Capistrano is a deployment automation tool built on Ruby, Rake, and SSH. Although Capistrano itself is written in Ruby, it can easily be used to deploy projects of any language or framework, be it Rails, Java, React, or PHP
1) Install the Capistrano gems
group :development do
gem 'capistrano', '~> 3.9'
gem 'capistrano-db-tasks', require: false
gem 'capistrano-rails', '~> 1.2'
gem 'capistrano-rvm'
gem 'capistrano3-puma'
end
NOTE: if you're using Resque you will need to add capistrano-resque as well
gem 'capistrano-resque', '~> 0.2.3', require: false
Run bundle
than bundle exec cap install
This creates all the necessary configuration files and directory structure for a Capistrano-enabled project with two stages, staging and production.
Please compare your Capfile
with following and add required gems here as well
# frozen_string_literal: true
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
require 'capistrano/scm/git'
install_plugin Capistrano::SCM::Git
# Include tasks from other gems included in your Gemfile
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/migrations'
require 'capistrano/puma'
require 'capistrano-resque'
require 'capistrano-db-tasks'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Nginx
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
2) SetUp deploy.rb
Replace the values in deploy.rb
with correct values
# config valid for current version and patch releases of Capistrano
lock '~> 3.11.0'
set :application, 'application_name'
set :repo_url, 'git@example.com:me/my_repo.git'
set :rails_env, fetch(:stage)
append :rvm_map_bins, 'rails'
set :deploy_to, "/var/www/html/#{fetch(:application)}"
set :format_options, command_output: true, log_file: 'log/capistrano.log', color: :auto, truncate: :false
set :rvm_type, :user
set :rvm_ruby_version, '2.5.0@gemset'
append :linked_files, 'config/database.yml', 'config/master.key'
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 'storage'
set :keep_releases, 5
Once you updated deploy.rb
file create database.yml
and master.key
in the deployment path and run cap production deploy:check
to check if there are any other configuration missing, if everything is worked fine run cap production deploy
, Here we go.
Our app should be deployed to production now!
3) SetUp deployment environments and nginx configuration
Rails have multiple environments that mean we can deploy our code in multiple servers with multiple domain, test
, staging
, and production
are most environment used in the rails community.
Let's update our config/deploy/production.rb
with the correct data and upload Nginx config to the server
# frozen_string_literal: true
set :branch, 'master'
set :resque_rails_env, 'production'
role :resque_worker, 'ip.000.00.ip'
role :resque_scheduler, 'ip.000.00.ip'
set :workers, '*' => 1
set :nginx_server_name, "your-domain.com #{fetch(:application)}.local"
server 'ip.000.00.ip',
user: 'ubuntu',
roles: %w[web app db]
Run, cap production puma:nginx_config
to setup nginx configuration and restart the nginx services in the server
sudo service nginx restart
Open the browser and specify the application address. www.your-domain.com
.