1. Install ruby using rbenv

1.1. Install rbenv

Install some dependencies for Ruby.

$ sudo apt-get update
$ sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev nodejs

Install rbenv and ruby-build plugins.

$ cd
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ exec $SHELL

$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
$ exec $SHELL

1.2. Install ruby & bundler gem

Install ruby.

$ rbenv install -v [RUBY VERSION] # ex) rbenv install -v 2.3.3
$ rbenv global [RUBY VERSION]
$ ruby -v # Check Ruby version

Install bundler gem.

$ echo "gem: --no-document" > ~/.gemrc
$ gem install bundler

2. Configure mysql, figaro and capistrano & Run deploy (Client side)

2.1. Configure ‘database.yml’ using mysql

Add gem to Gemfile:

# Gemfile
gem 'mysql2'

Configure database.yml

# config/database.yml
production:
  adapter: mysql2
  host: 127.0.0.1
  database: [my_app_name]_production
  username: root
  password: [my_mysql_password]
  pool: 5
  timeout: 5000

2.2. Make ‘application.yml’ using figaro

Add gem to Gemfile:

gem 'figaro'

Install figaro:

$ bundle && bundle exec figaro install

Generate ‘SECRET KEY’:

$ rake secret RAILS_ENV=production

Append the ‘SECRET KEY’ to ‘application.yml’

# config/application.yml
SECRET_KEY_BASE: [SECRET KEY]

2.3. Install the Capistrano gem

Add Capistrano to your Gemfile:

# Gemfile
group :development do
  gem 'capistrano'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano-passenger'
  gem 'capistrano-rbenv'
  gem 'capistrano-linked-files'
end

Then run Bundler to ensure Capistrano is downloaded and installed:

$ bundle && bundle exec cap install

2.4. Configure Capfile

Find the following lines, and uncomment them:

require "capistrano/rbenv"
set :rbenv_ruby, '2.3.3' # Add this line, with your ruby version
require "capistrano/bundler"
require "capistrano/passenger"
require "capistrano/linked_files"

2.5. Configure config/deploy.rb

Find the following lines, and uncomment them or add lines:

set :application, "my_app_name" # Your app name
set :repo_url, "git@example.com:me/my_repo.git" # Your app's git repo url

set :deploy_to, "/home/ubuntu/[my_app_name]"

append :linked_files, "config/application.yml", "config/database.yml", "config/secrets.yml"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "vendor/bundle", "public/system", "public/uploads", "public/assets"

set :keep_releases, 5
set :passenger_restart_with_touch, true
set :rails_env, :production

namespace :deploy do
  task :reset_db do
    on roles(:app), in: :groups, limit: 3, wait: 10 do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, "db:drop"
          execute :rake, "db:create"
          execute :rake, "db:migrate"
          execute :rake, "db:seed"
          # You can add additional rake task or some commands here
        end
      end
    execute :touch, release_path.join('tmp/restart.txt')
    end
  end
  task :assets do
    on roles(:app), in: :groups, limit: 3, wait: 10 do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, "assets:precompile"
        end
      end
      execute :touch, release_path.join('tmp/restart.txt')
    end
  end
end

2.6. Configure deploy/production.rb

Find the following lines, and uncomment them:

# deploy/production.rb
server 'example.com', # or Public IP
  user: 'ubuntu',
  roles: %w{app},
  ssh_options: {
    keys: %w(~/.ssh/example.pem), # Pem key file path on your local
    forward_agent: true, # See 0.4.1. below this codes
    auth_methods: %w(publickey)
  }

2.6.1. SSH Agent Forwarding

SSH Agent Forwarding is a great way to keep SSH keys manageable as it allows the deployment server to use your own local private key to authenticate to the git repository, instead of having to give your deployment server access to your git repository.

  • Only for macOS using keychain
$ ssh-add -K
  • All OS

Open up the file at ~/.ssh/config. If this file doesn’t exist, you can create it by entering touch ~/.ssh/config in the terminal. Enter the following text into the file, replacing example.com with your server’s domain name or IP:


Host example.com

  ForwardAgent yes


2.7. Upload linked_files using capistrano-linked-files

Run deploy command:

$ bundle exec cap production deploy

The error is occurred like:

ERROR linked file /home/ubuntu/[my_app_name]/shared/config/application.yml does not exist on example.com

But you must run deploy command to make ‘shared’ folder on the server, because the following command requires ‘shared’ folder. Capistrano make ‘shared’ folder when you run deploy command, so you can upload ‘linked_files’.

$ bundle exec cap production linked_files:upload_files

3. Passenger & nginx

3.1. Install passenger & nginx

Install some dependencies.

$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
$ sudo apt-get install -y apt-transport-https ca-certificates

Add Passenger APT repository.

$ sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main > /etc/apt/sources.list.d/passenger.list'
$ sudo apt-get update

Install Passenger & Nginx

$ sudo apt-get install -y nginx-extras passenger
$ sudo service nginx start

3.2. Configure passenger

$ sudo vi /etc/nginx/passenger.conf

Change the passenger_ruby line to point to your ruby executable

# /etc/nginx/passenger.conf
passenger_ruby /home/ubuntu/.rbenv/shims/ruby;

3.3. Configure nginx

$ sudo vi /etc/nginx/nginx.conf

Find the following lines, and uncomment them:

# /etc/nginx/nginx.conf
##
# Phusion Passenger
##
# Uncomment it if you installed ruby-passenger or ruby-passenger-enterprise
##

include /etc/nginx/passenger.conf;

And add the nginx host

$ sudo vi /etc/nginx/sites-enabled/default

Replace the file’s contents with the following

# /etc/nginx/sites-enabled/default
server {
        listen 80;
        listen [::]:80 ipv6only=on;

        server_name         example.com;
        passenger_enabled   on;
        rails_env           production;
        root                /home/ubuntu/[my_app_name]/current/public;

        # Add index.php to the list if you are using PHP
        # index index.html index.htm index.nginx-debian.html;

        ## Comment the following block
        # location / {
        #   # First attempt to serve request as file, then
        #   # as directory, then fall back to displaying a 404.
        #   try_files $uri $uri/ =404;
        # }

        # redirect server error pages to the static page /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}

Check the nginx configuration file.

$ sudo nginx -t

If syntax is ok and test is successful, Restart nginx.

$ sudo service nginx restart

4. Install Mysql

Install Mysql.

$ sudo apt-get install mysql-server mysql-client libmysqlclient-dev

5. Run deploy (Client side)

All deploy method includes passenger restart

$ bundle exec cap production deploy
$ bundle exec cap production deploy:reset_db
$ bundle exec cap production deploy:assets

Manually touch restart.txt

$ bundle exec cap production passenger:restart

Manually restart nginx (Server side)

$ sudo service nginx restart