Create the rails project
$ rails new capistrano-rails
$ cd capistrano-rails
Initialize Git
$ git init
$ git add .
$ git commit -am 'initial commit'
$ git remote add git@github.com:{username}/capistrano-rails.git
$ git push origin master
..
Add to .gitignore
.DS_Store
/config/database.yml
/config/secrets.yml
/config/local_env.yml
/public/assets
Edit Gemfile
$ vi Gemfile
gem 'mysql2'
gem 'unicorn'
group :development do
gem 'capistrano-rails'
gem 'capistrano-rvm'
gem 'capistrano3-unicorn'
end
Bundle!
$ bundle install
$ vim config/unicorn/production.rb
# set path to application
app_dir = File.expand_path("../../..", __FILE__)
shared_dir = "/home/deployer/apps/capistrano-rails/shared"
working_directory app_dir
# Set unicorn options
worker_processes 2
preload_app true
timeout 30
# Set up socket location
listen "#{shared_dir}/tmp/sockets/unicorn.sock", :backlog => 64
# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"
# Set master PID location
pid "#{shared_dir}/tmp/pids/unicorn.pid"
$ bundle exec cap install
Modify Capfile to include required assets
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
# Include tasks from other gems included in your Gemfile
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
Update Capistrano deploy.rb config
# config valid only for current version of Capistrano
lock '3.4.0'
set :application, 'capistrano-rails'
set :repo_url, 'git@github.com:eaconde/capistrano-rails.git'
# Default branch is :master
ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
# Default value for :linked_files is []
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
# Default value for linked_dirs is []
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
namespace :deploy do
desc "Restart unicorn server"
task :restart do
invoke 'unicorn:stop'
invoke 'unicorn:start'
end
after 'deploy:publishing', 'deploy:restart'
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
end
Update deploy/production.rb config file
$ vim config/deploy/production.rb
set :port, 22
set :user, 'deployer'
set :deploy_via, :remote_cache
set :use_sudo, false
server '[Update me after we know the droplet's IP]',
roles: [:web, :app, :db],
port: fetch(:port),
user: fetch(:user),
primary: true
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :ssh_options, {
forward_agent: true,
auth_methods: %w(publickey),
user: 'deployer',
}
set :rails_env, :production
set :conditionally_migrate, true
Generate keys with "rake secret"
$ vim ~/apps/capistrano-rails/shared/config/local_env.yml
SECRET_TOKEN: 1234567890...
SECRET_KEY_BASE: 1234567890...
Modify current application.rb to load and read local_env.yml
# config/application.rb
require File.expand_path('../boot', __FILE__)
require 'rails/all'
require 'yaml'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module CapistranoRails
class Application < Rails::Application
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
config.before_configuration do
env_file = File.join(Rails.root, 'config', 'local_env.yml')
YAML.load(File.open(env_file)).each do |key, value|
ENV[key.to_s] = value
end if File.exists?(env_file)
end
end
end
Create default page
$ rails g controller welcome index
Set default route
# config/routes.rb
Rails.application.routes.draw do
root to: "welcome#index"
end