Recipe for deploying Rails apps on AWS EC2


When I create a personal app in Rails and then deploy it on AWS, I always forget how to do it, so I'd like to write it down here.


--Assuming Rails 5.2 or higher

1. EC2 instance creation / key pair creation




image.png You can create a new key pair or an existing key pair. The key pair must not contain spaces.

2. Linking with Elastic IP





3. Open the port




Set the type to "HTTP", the protocol to "TCP", the port range to "80", and the source to "Custom /, :: / 0".

The following is also released so that HTTP connection can be made




4. Log in as EC2-user


$ cd ~

$ mkdir ~/.ssh
# .Create a directory called ssh
#Even if you get an error saying File exists.It means that the ssh directory exists, so let's proceed as it is.

$ mv Downloads/The name of the downloaded key.pem .ssh/
#Use the mv command to download the pem file from the download directory..Change to the ssh directory.

$ cd .ssh/

$ ls
#Check if the pem file exists

$chmod 600 The name of the downloaded key.pem

$ ssh -i Downloaded key name.pem [email protected] IP associated with the created EC2 instance
#(For example, Elastic IP is 123.456.If it's 789, ssh-i Downloaded key name.pem [email protected] command is 789)
#(Using the downloaded key, ec2-Login as user)

5. Required packages ・ Install Ruby


[[email protected] ~]$ sudo yum -y update
[[email protected] ~]$ sudo yum -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl libcurl-devel curl
[[email protected] ~]$ sudo curl -sL | sudo bash -
[[email protected] ~]$ sudo yum -y install nodejs
[[email protected] ~]$ git clone ~/.rbenv 
#Pass through
[[email protected] ~]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile 
#Description for calling rbenv
[[email protected] ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
#.bash_Load profile
[[email protected] ~]$ source .bash_profile
#ruby-install build
[[email protected] ~]$ git clone ~/.rbenv/plugins/ruby-build
#Do rehash
[[email protected] ~]$ rbenv rehash  
[[email protected] ~]$ rbenv install 2.5.1
[[email protected] ~]$ rbenv global 2.5.1
[ec[email protected] ~]$ rbenv rehash  #Do rehash
[[email protected] ~]$ ruby -v #Check version

#MySQL installation
[[email protected] ~]$ sudo yum -y install mysql56-server mysql56-devel mysql56
[[email protected] ~]$ sudo service mysqld start
[[email protected] ~]$ sudo /usr/libexec/mysql56/mysqladmin -u root password 'Password you want to set here'

#Check if you can enter with the PW set in MySQL
[[email protected] ~]$ mysql -u root -p

6. Register SSH key on Github

EC2 server

[[email protected] ~]$ ssh-keygen -t rsa -b 4096

You may be asked to enter about 3 steps such as passphrase on the way, but please proceed with the Enter key without entering anything.

EC2 server

[[email protected] ~]$ cat ~/.ssh/

Access the public key displayed on cat to Github and register it.


After registering the key on Github, check if you can connect with SSH with the following command

EC2 server

[[email protected] ~]$ ssh -T [email protected]

7. Capistrano preparation


group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'


$ bundle install
$ bundle exec cap install

Capfile editing

require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }


server '<Prepared Elastic IP>', user: 'ec2-user', roles: %w{app db web}


# config valid only for current version of Capistrano
#Described the version of capistrano. Continue to use the fixed version and prevent troubles due to version change
lock '<Capistrano version>'

#Used to display Capistrano logs
set :application, '<Own application name>'

#Specify from which repository you want to pull your app
set :repo_url,  '[email protected]:<Github username>/<Repository name>.git'

#Specify a directory to be referenced in common even if the version changes
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '<The version of ruby used in this app>' 

#Which public key to use for deployment
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['<Ssh key for EC2 instance on local PC(pem)Path to (eg~/.ssh/key_pem.pem)>'] 

#Location of the file containing the process number
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/" }

#Location of Unicorn configuration files
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

set :linked_files, %w{ config/master.key }

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:stop'
    invoke 'unicorn:start'

  desc 'upload master.key'
  task :upload do
    on roles(:app) do |host|
      if test "[ ! -d #{shared_path}/config ]"
        execute "mkdir -p #{shared_path}/config"
      upload!('config/master.key', "#{shared_path}/config/master.key")
  before :starting, 'deploy:upload'
  after :finishing, 'deploy:cleanup'


  <<: *default
  database: application_name_production
  username: root
  password: <%= ENV['DATABASE_PASSWORD'] %>
  socket: /var/lib/mysql/mysql.sock

8. Application server (unicorn) settings


group :production do
  gem 'unicorn', '5.4.1'


bundle install


app_path = File.expand_path('../../../', __FILE__)

worker_processes 1
#Specify current
working_directory "#{app_path}/current"

#Changed to refer to each in shared
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"

timeout 60

#The following is an applied setting, so the explanation is omitted.

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&

  if run_once
    run_once = false # prevent from firing again

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && != old_pid
      sig = ( + 1) >= server.worker_processes ? :QUIT : :TTOU
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection

config/environments/production.rb (after modification)

# config.assets.js_compressor = :uglifier

9. Clone code from Github

First, let's commit and push from GitHub Desktop. Be sure to do it on the master branch at this time.

ec2 server

#Create a new directory with the mkdir command
[[email protected] ~]$ sudo mkdir /var/www/
#Ec2 permissions on the created www directory-Change to user
[[email protected] ~]$ sudo chown ec2-user /var/www/


ec2 server

[[email protected] ~]$ cd /var/www/
[[email protected] www]$ git clone<username>/<Repository name>.git

10. Nginx settings

ec2 server

[[email protected] ~]$ sudo yum -y install nginx

#Start configuration file
[ec2-[email protected] ~]$ sudo vim /etc/nginx/conf.d/rails.conf


upstream app_server {
  #Changed to refer to in shared
  server unix:/var/www/<Application name>/shared/tmp/sockets/unicorn.sock;

server {
  listen 80;
  server_name <Fill in Elastic IP>;

#Set the maximum size of files uploaded from the client to 2 giga. The default is 1 mega, so keep it large
  client_max_body_size 2g;

  #Changed to refer to in current
  root /var/www/<Application name>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    #Changed to refer to in current
    root   /var/www/<Application name>/current/public;

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

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;

  error_page 500 502 503 504 /500.html;

ec2 server

#Change nginx permissions
[[email protected] ~]$ cd /var/lib
[[email protected] lib]$ sudo chmod -R 775 nginx  
[[email protected] lib]$ cd ~
[[email protected] ~]$ sudo service nginx restart
#nginx reboot
[[email protected] ~]$ sudo service nginx reload
[[email protected] ~]$ sudo service nginx restart

11. EC2 capacity expansion / bundler install

ec2 server

[[email protected] ~]$ cd
[[email protected] ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512
[[email protected] ~]$ sudo chmod 600 /swapfile1
[[email protected] ~]$ sudo mkswap /swapfile1
[[email protected] ~]$ sudo swapon /swapfile1
[[email protected] ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'

[[email protected] <Repository name>]$ gem install bundler -v x.x.x
#Introduce the locally confirmed version of bundler
[[email protected] <Repository name>]$ bundle install
#The above command may take several minutes or more.

12. Setting environment variables

ec2 server

[[email protected] <Repository name>]$ rake secret
#Copy string

ec2 server

[[email protected] ~]$ sudo vim /etc/environment


DATABASE_PASSWORD='MySQL root user password'
SECRET_KEY_BASE='The secret you copied earlier_key_base'

After writing, press esc (escape key) and enter: wq to save the contents. Once saved, log out to apply the environment variables.


$ ssh -i [The name of the downloaded key].pem ec2-user@[Elastic IP associated with the created EC2 instance]
(Using the downloaded key, ec2-Login as user)

ec2 server

[[email protected] ~]$ env | grep SECRET_KEY_BASE

[[email protected] ~]$ env | grep DATABASE_PASSWORD
DATABASE_PASSWORD='MySQL root user password'

ec2 server

#Production environment database creation
[[email protected] <Repository name>]$ cd /var/www/app name/releases
[[email protected] <Repository name>]$ ll 
#A folder with the name of the number representing the date is displayed Example: 20200218063515
cd bottom number#=>Example cd 20200218063515
[[email protected] <Repository name>]$ rails db:create RAILS_ENV=production
# => Created database '<Database name>'
[[email protected] <Repository name>]$ rails db:migrate RAILS_ENV=production

13. Automatic deployment

Push all local changes to master


#Run in the application directory
$ bundle exec cap production deploy

How to check the error log On the server side Check / var / www / <repository name> /current/log/unicorn.stderr.log with the less or cat command and check if there are any errors (the lower the log, the more up-to-date the log is. Note that it is UTC)

Recommended Posts

Recipe for deploying Rails apps on AWS EC2
Launch Rails on EC2
Deploy RAILS on EC2
Install docker on AWS EC2
For beginners! Automatic deployment with Rails6 + CircleCI + Capistrano + AWS (EC2)
[Rails] DB design for EC site
Error when deploying EC2 on CircleCI
Launch Rails on EC2 (manual deployment)
[EC2 / Vue / Rails] EC2 deployment procedure for Vue + Rails
[Rails] AWS EC2 instance environment construction
Tutorial 1 for building apps with Rails (First steps to Yay! You're on Rails!)
EFS mount on AWS Ubuntu EC2 (amazon-efs-utils)
Deployed using Docker + Rails + AWS (EC2 + RDS)
Easy deployment with Capistrano + AWS (EC2) + Rails
SCSS doesn't work when deploying Rails6 AWS
Try deploying a Rails app on EC2-Part 1-
Knowledge required to bring Rails apps to AWS
[Rails] Image posting by CarrierWave [AWS EC2]
Explanation of Ruby on rails for beginners ①
[Personal memo] Summary of stumbling blocks when deploying Rails apps to AWS
Validation settings for Ruby on Rails login function
[Ruby on Rails] Select2 introduction memo for Webpacker
[Rails] Procedure for linking databases with Ruby On Rails
Tailwind on Rails
EC2 on Docker-compose
Install docker-compose on a Graviton 2 instance of AWS EC2
How to install Ruby on an EC2 instance on AWS
Memo to build a Servlet environment on AWS EC2
Build a Ruby on Rails development environment on AWS Cloud9
Deploy laravel using docker on EC2 on AWS ① (Create EC2 instance)
Challenge the settings for developing with vue.js on Rails 6
Explanation of Ruby on rails for beginners ⑥ ~ Creation of validation ~
A high bill from AWS during development on rails ...
Explanation of Ruby on rails for beginners ② ~ Creating links ~
Explanation of Ruby on rails for beginners ⑦ ~ Flash implementation ~