13 July 2015

Complete Tutorial

http://capistranorb.com/
http://robmclarty.com/blog/how-to-deploy-a-rails-4-app-with-git-and-capistrano
http://dylanmarkow.com/blog/2014/01/08/capistrano-3-setting-a-default-stage/
http://robmclarty.com/blog/how-to-deploy-a-rails-4-app-with-git-and-capistrano
https://github.com/bkeepers/dotenv-deployment
http://corlewsolutions.com/articles/article-10-how-to-deploy-rails-applications-using-capistrano-3-1-and-windows-7
http://vladigleba.com/blog/2014/04/10/deploying-rails-apps-part-6-writing-capistrano-tasks/
http://www.rubytreesoftware.com/resources/ruby-on-rails-41-ubuntu-1404-server-deployment

# gemfile
# Use Capistrano for deployment
group :development do
  gem "capistrano", '~> 3.4.0'
  gem 'capistrano-rails', '~> 1.1'
  gem "capistrano-rvm"
  # IO lib to hide password input when doing capistrano
  gem 'highline', '~> 1.7.1'
  gem 'rvm1-capistrano3', require: false
end


$ bundle install

cd /path/to/your/project
$ bundle exec cap install
# deploy.rb
set :application, "YourApplicationName"
set :repo_url, "git@github.com:your-username/your-repository-name.git"
set :deploy_to, "/path/to/your/app/in/server"     ----------------->>>>>>>> manually create the folder
set :deploy_via, :copy
set :rails_env, 'production'
set :rake_env, 'production'
set :scm, :git
set :branch, "master"
set :log_level, :debug
set :ssh_options, { paranoid: false }
set :pty, true
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', 'config/deploy/production.rb')
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/uploads')
set :keep_releases, 5
set :bundle_binstubs, -> { release_path.join('bin') }
#Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'rvm1/capistrano3'
# config/deploy/production.rb
role :app, %w{deploy@example.com}
role :web, %w{deploy@example.com}
role :db,  %w{deploy@example.com}


# Extended Server Syntax
# ======================
# This can be used to drop a more detailed server definition into the
# server list. The second argument is a, or duck-types, Hash and is
# used to set extended properties on the server.

server 'example.com', user: 'user', roles: %w{web app db}, primary: true

set :deploy_to, '/dir/to/app/in/production_server/'
set :deploy_user, 'root'
set :use_sudo, false
set :user, 'root'


set :default_environment, {
  'PATH' => "$PATH",
  'RUBY_VERSION' => 'ruby 2.2.0',
  'GEM_HOME'     => '/home/user/.rvm/gems/ruby-2.2.0',
  'GEM_PATH'     => '/home/user/.rvm/gems/ruby-2.2.0',
  'BUNDLE_PATH'  => '/home/user/.rvm/gems/ruby-2.2.0'  # If you are using bundler.
}

Capistrano rake tasks

namespace :setup do

  desc "Upload deploy-production, database.yml and secrets.yml files."
  task :upload_sensitive_files do
    on roles(:app) do
      execute "mkdir -p #{shared_path}/config"
      upload! StringIO.new(File.read("config/database.yml")), "#{shared_path}/config/database.yml"
      upload! StringIO.new(File.read("config/secrets.yml")), "#{shared_path}/config/secrets.yml"
      execute "mkdir -p #{shared_path}/config/deploy"
      upload! StringIO.new(File.read("config/deploy/production.rb")), "#{shared_path}/config/deploy/production.rb"
    end
  end

  desc "Seed the database."
  task :seed_db do
    on roles(:app) do
      within "#{current_path}" do
        with rails_env: :production do
          execute :rake, "db:seed"
        end
      end
    end
  end

  desc "Symlinks config files for Nginx and Unicorn."
  task :symlink_config do
    on roles(:app) do
      execute "rm -f /etc/nginx/sites-enabled/default"

      execute "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/sites-enabled/#{fetch(:application)}"
      # execute "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{fetch(:application)}"
   end
  end

end

Preparing the server

sudo groupadd deploy
sudo useradd deploy
sudo passwd deploy
visudo  --> añadir linea deploy ALL=(ALL) ALL
sudo usermod -G deploy deploy
sudo chown -R deploy:deploy deploy_to_path
sudo chmod g+w deploy_to_path

Enable passwordless sudo for user deploy

visudo (como root, y añadir)
deploy ALL=NOPASSWD:/etc/init.d/nginx

Setup SSH

http://robmclarty.com/blog/how-to-setup-a-production-server-for-rails-4

cp /etc/ssh/sshd_config ~
vi /etc/ssh/sshd_config

# sshd_config
Port 22222
PermitRootLogin no
...
AllowUsers deploy alfredo    ---> at the very bottom of the file

Restart the service

service ssh restart
/etc/init.d/ssh restart
systemctl restart sshd

Setup deployment

$ cap production rvm:check
$ cap production deploy
$ cap production setup:upload_sensitive_files
$ cap production deploy

Login server, cd /app_folder/releases/<release> and execute
$ bundle exec rake db:create
$ bundle exec rake db:seed

Manage passwords and secrets

Create .env_vars with

SHARINGKITCHN_SECRET_KEY_BASE=5e29f57f14c304f21d0ebc6a83c1634dae9c3c2ecf49c1eb7398edd12905b4341428a8bf6103aa3cdd4d832e1a99677d8529e1627248a108a8f153a3947f8769
SHARINGKITCHN_DATABASE_PASSWORD=<pw>

En deploy.rb

set :linked_files, %w{config/database.yml config/.env-vars}

Add to .gitignore database.yml .env_vars

Copy manually to shared folder/config

How to enter rails console on production via capistrano?

On production server

bundle exec rails console

As a capistrano task

namespace :rails do
  desc "Remote console"
  task :console, :roles => :app do
    run_interactively "bundle exec rails console #{rails_env}"
  end

  desc "Remote dbconsole"
  task :dbconsole, :roles => :app do
    run_interactively "bundle exec rails dbconsole #{rails_env}"
  end
end

def run_interactively(command)
  server ||= find_servers_for_task(current_task).first
  exec %Q(ssh #{user}@#{myproductionhost} -t '#{command}')
end
cap rails:console