SlideShare a Scribd company logo
1 of 40
Download to read offline
Practical Chef and Capistrano
              For Your Rails Application




Dan Ivovich
SLS Internal Dec 2012
12/17/12
Dan Ivovich
          SmartLogic Solutions

http://smartlogicsolutions.com
Twitter - @danivovich

Dan Ivovich on GitHub
What is the goal?
● Build a machine that can run the application
  quickly and repeatedly

● Make deploying the app, upgrading
  components, adding components, etc seamless
  and easy
Who does what?
● Chef
  ○ User / SSH Keys
  ○ Web server
  ○ Database
  ○ Postfix
  ○ Redis / Memcached
  ○ Monit
  ○ NewRelic Server monitoring
  ○ /etc/hosts
  ○ rbenv & Ruby
  ○ Application binary dependencies (i.e.
     Sphinx)
Who does what?
● Capistrano
  ○ Virtual Hosts
  ○ Unicorn init.d script
  ○ Unicorn.rb
  ○ Monit process monitors
  ○ Normal Capistrano Stuff
Why both?
● Use each for what it is best at
● Chef is for infrastructure
● Capistrano is for the app
● Could have more than one Capistrano app with
  the same Chef config
● Chef config changes infrequently, Capistrano
  config could change more frequently
How? - Chef
●   Standard Recipes
●   Custom Recipes
●   Recipes assigned to Roles
●   Roles assigned to Nodes
●   Nodes with attributes to tailor the install
How? - Capistrano
● Standard Tasks
● Custom Tasks
● Templating files
Chef - Getting started
● Gemfile




● knife kitchen chef-repo
  ○ Create the folder structure you need
● Solo specific stuff (chef-repo/.chef/knife.rb)



● knife cookbook site install nginx
  ○ Get the nginx cookbook and anything it
     needs
Custom cookbook
● knife cookbook create your_app_custom




● Edit:
     chef-repo/cookbooks/your_app_custom/recipes/default.rb
package "logrotate"

rbenv_ruby node['your_app']['ruby_version']

rbenv_gem "bundler" do
 ruby_version node['your_app']['ruby_version']
end

template "/etc/hosts" do
 source "hosts.erb"
 mode "0644"
 owner "root"
 group "root"
end
directory "#{node['your_app']['cap_base']}" do
 action :create
 owner 'deploy'
 group 'deploy'
 mode '0755'
end

directory "#{node['your_app']['deploy_to']}/shared" do
 action :create
 owner 'deploy'
 group 'deploy'
 mode '0755'
end

template "#{node['your_app']['deploy_to']}/shared/database.yml"
do
 source 'database.yml.erb'
 owner 'deploy'
 group 'deploy'
 mode '0644'
end
Recipe Templates
●   chef-repo/cookbooks/your_app_custom/templates/default/database.yml.erb



<%= node['your_app']['environment'] %>:
 adapter: <%= node['your_app']['adapter'] %>
 database: <%= node['your_app']['database'] %>
 username: <%= node['your_app']['database_user'] %>
<% if node['your_app']['database_password'] %>
 password: <%= node['your_app']['database_password'] %>
<% end %>
 host: <%= node['your_app']['database_host'] %>
 encoding: utf8
 min_messages: warning
Node Attributes
● Application namespace
  ○ chef-repo/cookbooks/your_app_custom/attributes/default.rb
default['your_app']['cap_base']          = '/home/deploy/apps'
default['your_app']['deploy_to']         = '/home/deploy/apps/your_app'
default['your_app']['environment']       = 'production'
default['your_app']['database']          = 'your_app'
default['your_app']['adapter']           = 'postgresql'
default['your_app']['database_user']     = 'postgres'
default['your_app']['database_password'] =
   (node['postgresql']['password']['postgres'] rescue nil)
default['your_app']['database_host']     = 'localhost'
default['your_app']['ruby_version']      = '1.9.2-p320'
Node Attributes
● For your Node configuration
  "your_app" : {
    "environment" : "production",
    "database" : "your_app",
    "database_user" : "your_app_db_user",
    "database_host" : "db1",
    "hosts" : {
      "db1" : "nn.nn.nn.nn"
    }
  },
Define Roles
  chef-repo/roles/web_server.rb
name "web_server"
description "web server setup"
run_list [
  "recipe[build-essential]", "recipe[annoyances]", "recipe[openssl]",
  "recipe[openssh]", "recipe[sudo]", "recipe[postgresql::client]",
  "recipe[users_solo::admins]", "recipe[sphinx]", "recipe[imagemagick]",
  "recipe[nginx]", "recipe[rbenv]", "recipe[postfix]",
  "recipe[monit]", "recipe[your_app_custom]"
]
default_attributes 'build-essential' => { 'compiletime' => true }
Node Configuration
{
    "openssh" : { "permit_root_login" : "no", "password_authentication": "no" },
    "authorization" : {
      "sudo" : { "groups" : [ "admin", "sudo" ], "passwordless" : true }
    },
    "rbenv" : { "group_users" : [ "deploy" ] },
    "sphinx" : { "use_mysql" : false, "use_postgres" : true },
    "your_app" : {
      "environment" : "production",
      "database" : "your_app",
      "database_user" : "your_app_db_user",
      "database_host" : "db1",
      "hosts" : { "db1" : "nn.nn.nn.nn" }
    },
    "run_list": [
      "role[web_server]"
    ]
}
Not so bad!
Go!
●   bundle exec knife bootstrap -x super_user node_name 
        --template-file=ubuntu-12.04-lts.erb




●   bundle exec knife cook super_user@node_name

●   Relax!
Capistrano - Getting Started
● Add capistrano and capistrano-ext
● Capify
● deploy.rb
Capistrano - deploy.rb
require 'bundler/capistrano'
require 'capistrano/ext/multistage'

load 'config/recipes/base'
load 'config/recipes/nginx'
load 'config/recipes/unicorn'
load 'config/recipes/monit'

set :default_environment, {
  'PATH' => "/opt/rbenv/shims:/opt/rbenv/bin:$PATH",
  'RBENV_ROOT' => "/opt/rbenv"
}
set :bundle_flags, "--deployment --quiet --binstubs --shebang ruby-local-exec"
set :use_sudo, false
set :application, 'your_app'
set :repository, 'git@github.com:you/your_app.git'
set :deploy_to, '/home/deploy/apps/your_app'
set :deploy_via, :remote_cache
Capistrano - deploy.rb
set :branch, 'master'
set :scm, :git
set :target_os, :ubuntu
set :maintenance_template_path, File.expand_path("..
/recipes/templates/maintenance.html.erb", __FILE__)

default_run_options[:pty] = true
ssh_options[:forward_agent] = true

namespace :custom do
 desc 'Create the .rbenv-version file'
 task :rbenv_version, :roles => :app do
  run "cd #{release_path} && rbenv local 1.9.2-p320"
 end
end

before 'bundle:install', 'custom:rbenv_version'
Capistrano - recipes/base.rb
def template(from, to)
 erb = File.read(File.expand_path("../templates/#{from}", __FILE__))
 put ERB.new(erb).result(binding), to
end

def set_default(name, *args, &block)
 set(name, *args, &block) unless exists?(name)
end
Capistrano - recipes/monit.rb
set_default(:alert_email, "dan@smartlogicsolutions.com")
namespace :monit do
 desc "Setup all Monit configuration"
 task :setup do
  unicorn
  syntax
  restart
 end
 after "deploy:setup", "monit:setup"

 task(:unicorn, roles: :app) { monit_config "unicorn" }

 %w[start stop restart syntax].each do |command|
  desc "Run Monit #{command} script"
  task command do
   with_user "deploy" do
     sudo "service monit #{command}"
    end
  end
 end
end
Capistrano - recipes/monit.rb

def monit_config(name, destination = nil)
 destination ||= "/etc/monit/conf.d/#{name}.conf"
 template "monit/#{name}.erb", "/tmp/monit_#{name}"
 with_user "deploy" do
  sudo "mv /tmp/monit_#{name} #{destination}"
  sudo "chown root #{destination}"
  sudo "chmod 600 #{destination}"
 end
end
Capistrano - recipes/nginx.rb
namespace :nginx do
 desc "Setup nginx configuration for this application"
 task :setup, roles: :web do
  template "nginx_unicorn.erb", "/tmp/nginx_conf"
  sudo "mv /tmp/nginx_conf /etc/nginx/sites-enabled/#{application}"
  sudo "rm -f /etc/nginx/sites-enabled/default"
  restart
 end
 after "deploy:setup", "nginx:setup"

 %w[start stop restart].each do |command|
  desc "#{command} nginx"
  task command, roles: :web do
   sudo "service nginx #{command}"
  end
 end
end
Capistrano - templates/nginx_unicorn.erb
upstream unicorn {
  server unix:/tmp/unicorn.<%= application %>.sock fail_timeout=0;
}
server {
  listen 80 default deferred;
  server_name your_app_domain.com;
  root <%= current_path %>/public;
  if (-f $document_root/system/maintenance.html) {
    return 503;
  }
  error_page 503 @maintenance;
  location @maintenance {
    rewrite ^(.*)$ /system/maintenance.html last;
    break;
  }
  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control 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_set_header X-Forwarded-Proto $scheme;
    proxy_redirect off;
    proxy_pass http://unicorn;
  }
  error_page 500 502 /500.html;
  error_page 504 /504.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
  server_tokens off;
}
Capistrano - recipes/unicorn.rb
set_default(:unicorn_user) { user }
set_default(:unicorn_pid) { "#{current_path}/tmp/pids/unicorn.pid" }
set_default(:unicorn_config) { "#{shared_path}/config/unicorn.rb" }
set_default(:unicorn_log) { "#{shared_path}/log/unicorn.log" }
set_default(:unicorn_workers) {
  if rails_env == "production"
    10
  else
    3
  end
}
set_default(:unicorn_timeout, 30)
Capistrano - recipes/unicorn.rb
namespace :unicorn do
 desc "Setup Unicorn initializer and app configuration"
 task :setup, roles: :app do
  run "mkdir -p #{shared_path}/config"
  template "unicorn.rb.erb", unicorn_config
  template "unicorn_init.erb", "/tmp/unicorn_init"
  run "chmod +x /tmp/unicorn_init"
  sudo "mv /tmp/unicorn_init /etc/init.d/unicorn_#{application}"
  sudo "update-rc.d -f unicorn_#{application} defaults"
 end
 after "deploy:setup", "unicorn:setup"

 %w[start stop restart].each do |command|
  desc "#{command} unicorn"
  task command, roles: :app do
   sudo "service unicorn_#{application} #{command}"
  end
  after "deploy:#{command}", "unicorn:#{command}"
 end
end
Capistrano - templates/unicorn.rb.erb


root = "<%= current_path %>"
working_directory root
pid "#{root}/tmp/pids/unicorn.pid"
stderr_path "#{root}/log/unicorn.log"
stdout_path "#{root}/log/unicorn.log"
listen "/tmp/unicorn.<%= application %>.sock"
worker_processes <%= unicorn_workers %>
timeout <%= unicorn_timeout %>
preload_app true

before_exec { |server| ENV['BUNDLE_GEMFILE'] = "#{root}/Gemfile" }
Capistrano - templates/unicorn.rb.erb


before_fork do |server, worker|
 # Disconnect since the database connection will not carry over
 if defined? ActiveRecord::Base
   ActiveRecord::Base.connection.disconnect!
 end
 # Quit the old unicorn process
 old_pid = "#{server.config[:pid]}.oldbin"
 if File.exists?(old_pid) && server.pid != old_pid
   begin
    Process.kill("QUIT", File.read(old_pid).to_i)
   rescue Errno::ENOENT, Errno::ESRCH
    # someone else did our job for us
   end
 end
end
Capistrano - templates/unicorn.rb.erb




after_fork do |server, worker|
 # Start up the database connection again in the worker
 if defined?(ActiveRecord::Base)
   ActiveRecord::Base.establish_connection
 end
 child_pid = server.config[:pid].sub(".pid", ".#{worker.nr}.pid")
 system("echo #{Process.pid} > #{child_pid}")
end
Capistrano - t/monit/unicorn.erb

check process <%= application %>_unicorn with pidfile <%= unicorn_pid %>
 start program = "/etc/init.d/unicorn_<%= application %> start"
 stop program = "/etc/init.d/unicorn_<%= application %> stop"

<% unicorn_workers.times do |n| %>
 <% pid = unicorn_pid.sub(".pid", ".#{n}.pid") %>
 check process <%= application %>_unicorn_worker_<%= n %> with pidfile <%= pid %>
  start program = "/bin/true"
  stop program = "/usr/bin/test -s <%= pid %> && /bin/kill -QUIT `cat <%= pid %>`"
  if mem > 200.0 MB for 1 cycles then restart
  if cpu > 50% for 3 cycles then restart
  if 5 restarts within 5 cycles then timeout
  alert <%= alert_email %> only on { pid }
  if changed pid 2 times within 60 cycles then alert
<% end %>
Whoa!
But really, it is just a
bunch of Erb for files you
      already have
Did you see the trick?

● after "deploy:setup", "nginx:setup"


                  So we can...

● cap staging deploy:setup deploy:migrations
From the top!
Ready?!? Here we go!

1. New VM at my_web_app in your .ssh/config
2. Create chef-repo/nodes/my_web_app.json
3. In chef-repo:
       bundle exec knife bootstrap node_name 
        --template-file=ubuntu-12.04-lts.erb
4.   bundle exec knife cook root@my_web_app
5.   In app directory:
       create/edit config/deploy/staging.rb
6.   cap staging deploy:setup deploy:migrations
7.   Hit the bars
Thoughts....
● Vagrant and VMs are you friend. Rinse and repeat
● It is ok to tweak your Chef stuff and re-cook, but I always
   like to restart with a fresh VM once I think I'm done
● Capistrano tweaks should be easy to apply, especially with
   tasks like nginx:setup, unicorn:setup etc.
● Chef issues are harder to debug and more frustrating than
   Capistrano issues, another reason to put more app specific
   custom stuff in Capistrano and do standard things in Chef
Questions?
http://smartlogicsolutions.com

http://twitter.com/smartlogic

http://github.com/smartlogic
 
http://fb.me/smartlogic

More Related Content

What's hot

Dev ninja -> vagrant + virtualbox + chef-solo + git + ec2
Dev ninja  -> vagrant + virtualbox + chef-solo + git + ec2Dev ninja  -> vagrant + virtualbox + chef-solo + git + ec2
Dev ninja -> vagrant + virtualbox + chef-solo + git + ec2Yros
 
[20180226] I understand webpacker perfectly
[20180226] I understand webpacker perfectly[20180226] I understand webpacker perfectly
[20180226] I understand webpacker perfectlyYuta Suzuki
 
Automation and Ansible
Automation and AnsibleAutomation and Ansible
Automation and Ansiblejtyr
 
DevOps tools for everyone - Vagrant, Puppet and Webmin
DevOps tools for everyone - Vagrant, Puppet and WebminDevOps tools for everyone - Vagrant, Puppet and Webmin
DevOps tools for everyone - Vagrant, Puppet and Webminpostrational
 
MeaNstack on Docker
MeaNstack on DockerMeaNstack on Docker
MeaNstack on DockerDaniel Ku
 
chef loves windows
chef loves windowschef loves windows
chef loves windowsMat Schaffer
 
Getting Started with Ansible
Getting Started with AnsibleGetting Started with Ansible
Getting Started with AnsibleAhmed AbouZaid
 
Bower - A package manager for the web
Bower - A package manager for the webBower - A package manager for the web
Bower - A package manager for the webLarry Nung
 
Getting Started with Capistrano in Ten Easy Steps
Getting Started with Capistrano in Ten Easy StepsGetting Started with Capistrano in Ten Easy Steps
Getting Started with Capistrano in Ten Easy Stepselliando dias
 
Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)
Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)
Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)akira6592
 
Bower & Grunt - A practical workflow
Bower & Grunt - A practical workflowBower & Grunt - A practical workflow
Bower & Grunt - A practical workflowRiccardo Coppola
 
Custom Non-RDS Multi-AZ Mysql Replication
Custom Non-RDS Multi-AZ Mysql ReplicationCustom Non-RDS Multi-AZ Mysql Replication
Custom Non-RDS Multi-AZ Mysql ReplicationMichael H. Oshita
 
Capistrano - automate all the things
Capistrano - automate all the thingsCapistrano - automate all the things
Capistrano - automate all the thingsJohn Cleary
 
Deploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoDeploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoAlmir Mendes
 
Ansible Meetup Hamburg / Quickstart
Ansible Meetup Hamburg / QuickstartAnsible Meetup Hamburg / Quickstart
Ansible Meetup Hamburg / QuickstartHenry Stamerjohann
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with CapistranoLaunchAny
 
Tdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema RubyTdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema RubyFabio Akita
 

What's hot (20)

Dev ninja -> vagrant + virtualbox + chef-solo + git + ec2
Dev ninja  -> vagrant + virtualbox + chef-solo + git + ec2Dev ninja  -> vagrant + virtualbox + chef-solo + git + ec2
Dev ninja -> vagrant + virtualbox + chef-solo + git + ec2
 
[20180226] I understand webpacker perfectly
[20180226] I understand webpacker perfectly[20180226] I understand webpacker perfectly
[20180226] I understand webpacker perfectly
 
Front-end tools
Front-end toolsFront-end tools
Front-end tools
 
Automation and Ansible
Automation and AnsibleAutomation and Ansible
Automation and Ansible
 
DevOps tools for everyone - Vagrant, Puppet and Webmin
DevOps tools for everyone - Vagrant, Puppet and WebminDevOps tools for everyone - Vagrant, Puppet and Webmin
DevOps tools for everyone - Vagrant, Puppet and Webmin
 
MeaNstack on Docker
MeaNstack on DockerMeaNstack on Docker
MeaNstack on Docker
 
chef loves windows
chef loves windowschef loves windows
chef loves windows
 
Getting Started with Ansible
Getting Started with AnsibleGetting Started with Ansible
Getting Started with Ansible
 
Bower - A package manager for the web
Bower - A package manager for the webBower - A package manager for the web
Bower - A package manager for the web
 
Ansible intro
Ansible introAnsible intro
Ansible intro
 
Getting Started with Capistrano in Ten Easy Steps
Getting Started with Capistrano in Ten Easy StepsGetting Started with Capistrano in Ten Easy Steps
Getting Started with Capistrano in Ten Easy Steps
 
Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)
Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)
Ansibleではじめるサーバー・ネットワークの自動化(2019/02版)
 
Bower & Grunt - A practical workflow
Bower & Grunt - A practical workflowBower & Grunt - A practical workflow
Bower & Grunt - A practical workflow
 
Capistrano
CapistranoCapistrano
Capistrano
 
Custom Non-RDS Multi-AZ Mysql Replication
Custom Non-RDS Multi-AZ Mysql ReplicationCustom Non-RDS Multi-AZ Mysql Replication
Custom Non-RDS Multi-AZ Mysql Replication
 
Capistrano - automate all the things
Capistrano - automate all the thingsCapistrano - automate all the things
Capistrano - automate all the things
 
Deploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoDeploying Rails Applications with Capistrano
Deploying Rails Applications with Capistrano
 
Ansible Meetup Hamburg / Quickstart
Ansible Meetup Hamburg / QuickstartAnsible Meetup Hamburg / Quickstart
Ansible Meetup Hamburg / Quickstart
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with Capistrano
 
Tdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema RubyTdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema Ruby
 

Similar to Practical Chef and Capistrano for Your Rails App

2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOpsОмские ИТ-субботники
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
Chef or how to make computers do the work for us
Chef or how to make computers do the work for usChef or how to make computers do the work for us
Chef or how to make computers do the work for ussickill
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesLindsay Holmwood
 
Bangpypers april-meetup-2012
Bangpypers april-meetup-2012Bangpypers april-meetup-2012
Bangpypers april-meetup-2012Deepak Garg
 
Automating complex infrastructures with Puppet
Automating complex infrastructures with PuppetAutomating complex infrastructures with Puppet
Automating complex infrastructures with PuppetKris Buytaert
 
Capistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient wayCapistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient waySylvain Rayé
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsMongoDB
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsMongoDB
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto Artnik
 
Automating Complex Setups with Puppet
Automating Complex Setups with PuppetAutomating Complex Setups with Puppet
Automating Complex Setups with PuppetKris Buytaert
 
X64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newX64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newYiwei Ma
 
Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013Cosimo Streppone
 
Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...
Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...
Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...Nagios
 
From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012Carlos Sanchez
 

Similar to Practical Chef and Capistrano for Your Rails App (20)

Cooking with Chef
Cooking with ChefCooking with Chef
Cooking with Chef
 
Chef solo the beginning
Chef solo the beginning Chef solo the beginning
Chef solo the beginning
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
 
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Chef or how to make computers do the work for us
Chef or how to make computers do the work for usChef or how to make computers do the work for us
Chef or how to make computers do the work for us
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
Bangpypers april-meetup-2012
Bangpypers april-meetup-2012Bangpypers april-meetup-2012
Bangpypers april-meetup-2012
 
Automating complex infrastructures with Puppet
Automating complex infrastructures with PuppetAutomating complex infrastructures with Puppet
Automating complex infrastructures with Puppet
 
Capistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient wayCapistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient way
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.js
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.js
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Automating Complex Setups with Puppet
Automating Complex Setups with PuppetAutomating Complex Setups with Puppet
Automating Complex Setups with Puppet
 
Chef training - Day2
Chef training - Day2Chef training - Day2
Chef training - Day2
 
X64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newX64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 new
 
Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013Puppet at Opera Sofware - PuppetCamp Oslo 2013
Puppet at Opera Sofware - PuppetCamp Oslo 2013
 
MongoDB and Node.js
MongoDB and Node.jsMongoDB and Node.js
MongoDB and Node.js
 
Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...
Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...
Nagios Conference 2014 - Mike Weber - Expanding NRDS Capabilities on Linux Sy...
 
From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012
 

More from SmartLogic

Writing Game Servers with Elixir
Writing Game Servers with ElixirWriting Game Servers with Elixir
Writing Game Servers with ElixirSmartLogic
 
All Aboard The Stateful Train
All Aboard The Stateful TrainAll Aboard The Stateful Train
All Aboard The Stateful TrainSmartLogic
 
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan IvovichDC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan IvovichSmartLogic
 
Monitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with PrometheusMonitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with PrometheusSmartLogic
 
Going Multi-Node
Going Multi-NodeGoing Multi-Node
Going Multi-NodeSmartLogic
 
Kubernetes and docker
Kubernetes and dockerKubernetes and docker
Kubernetes and dockerSmartLogic
 
Serializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSerializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSmartLogic
 
Guide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei EllerbrockGuide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei EllerbrockSmartLogic
 
Introduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogicIntroduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogicSmartLogic
 
How SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan IvovichHow SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan IvovichSmartLogic
 
A Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageA Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageSmartLogic
 
Effective ActiveRecord
Effective ActiveRecordEffective ActiveRecord
Effective ActiveRecordSmartLogic
 
An Introduction to Reactive Cocoa
An Introduction to Reactive CocoaAn Introduction to Reactive Cocoa
An Introduction to Reactive CocoaSmartLogic
 
iOS Development Methodology
iOS Development MethodologyiOS Development Methodology
iOS Development MethodologySmartLogic
 
CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!SmartLogic
 
From Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to CodeFrom Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to CodeSmartLogic
 
The Language of Abstraction in Software Development
The Language of Abstraction in Software DevelopmentThe Language of Abstraction in Software Development
The Language of Abstraction in Software DevelopmentSmartLogic
 
Android Testing: An Overview
Android Testing: An OverviewAndroid Testing: An Overview
Android Testing: An OverviewSmartLogic
 
Intro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS DevelopmentIntro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS DevelopmentSmartLogic
 
Logstash: Get to know your logs
Logstash: Get to know your logsLogstash: Get to know your logs
Logstash: Get to know your logsSmartLogic
 

More from SmartLogic (20)

Writing Game Servers with Elixir
Writing Game Servers with ElixirWriting Game Servers with Elixir
Writing Game Servers with Elixir
 
All Aboard The Stateful Train
All Aboard The Stateful TrainAll Aboard The Stateful Train
All Aboard The Stateful Train
 
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan IvovichDC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
 
Monitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with PrometheusMonitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with Prometheus
 
Going Multi-Node
Going Multi-NodeGoing Multi-Node
Going Multi-Node
 
Kubernetes and docker
Kubernetes and dockerKubernetes and docker
Kubernetes and docker
 
Serializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSerializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara Hacopian
 
Guide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei EllerbrockGuide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei Ellerbrock
 
Introduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogicIntroduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogic
 
How SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan IvovichHow SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan Ivovich
 
A Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageA Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming Language
 
Effective ActiveRecord
Effective ActiveRecordEffective ActiveRecord
Effective ActiveRecord
 
An Introduction to Reactive Cocoa
An Introduction to Reactive CocoaAn Introduction to Reactive Cocoa
An Introduction to Reactive Cocoa
 
iOS Development Methodology
iOS Development MethodologyiOS Development Methodology
iOS Development Methodology
 
CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!
 
From Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to CodeFrom Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to Code
 
The Language of Abstraction in Software Development
The Language of Abstraction in Software DevelopmentThe Language of Abstraction in Software Development
The Language of Abstraction in Software Development
 
Android Testing: An Overview
Android Testing: An OverviewAndroid Testing: An Overview
Android Testing: An Overview
 
Intro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS DevelopmentIntro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS Development
 
Logstash: Get to know your logs
Logstash: Get to know your logsLogstash: Get to know your logs
Logstash: Get to know your logs
 

Recently uploaded

Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsYoss Cohen
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Nikki Chapple
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...itnewsafrica
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfAarwolf Industries LLC
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxAna-Maria Mihalceanu
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 

Recently uploaded (20)

Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platforms
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdf
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance Toolbox
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 

Practical Chef and Capistrano for Your Rails App

  • 1. Practical Chef and Capistrano For Your Rails Application Dan Ivovich SLS Internal Dec 2012 12/17/12
  • 2. Dan Ivovich SmartLogic Solutions http://smartlogicsolutions.com Twitter - @danivovich Dan Ivovich on GitHub
  • 3. What is the goal? ● Build a machine that can run the application quickly and repeatedly ● Make deploying the app, upgrading components, adding components, etc seamless and easy
  • 4. Who does what? ● Chef ○ User / SSH Keys ○ Web server ○ Database ○ Postfix ○ Redis / Memcached ○ Monit ○ NewRelic Server monitoring ○ /etc/hosts ○ rbenv & Ruby ○ Application binary dependencies (i.e. Sphinx)
  • 5. Who does what? ● Capistrano ○ Virtual Hosts ○ Unicorn init.d script ○ Unicorn.rb ○ Monit process monitors ○ Normal Capistrano Stuff
  • 6. Why both? ● Use each for what it is best at ● Chef is for infrastructure ● Capistrano is for the app ● Could have more than one Capistrano app with the same Chef config ● Chef config changes infrequently, Capistrano config could change more frequently
  • 7. How? - Chef ● Standard Recipes ● Custom Recipes ● Recipes assigned to Roles ● Roles assigned to Nodes ● Nodes with attributes to tailor the install
  • 8. How? - Capistrano ● Standard Tasks ● Custom Tasks ● Templating files
  • 9. Chef - Getting started ● Gemfile ● knife kitchen chef-repo ○ Create the folder structure you need ● Solo specific stuff (chef-repo/.chef/knife.rb) ● knife cookbook site install nginx ○ Get the nginx cookbook and anything it needs
  • 10. Custom cookbook ● knife cookbook create your_app_custom ● Edit: chef-repo/cookbooks/your_app_custom/recipes/default.rb
  • 11. package "logrotate" rbenv_ruby node['your_app']['ruby_version'] rbenv_gem "bundler" do ruby_version node['your_app']['ruby_version'] end template "/etc/hosts" do source "hosts.erb" mode "0644" owner "root" group "root" end
  • 12. directory "#{node['your_app']['cap_base']}" do action :create owner 'deploy' group 'deploy' mode '0755' end directory "#{node['your_app']['deploy_to']}/shared" do action :create owner 'deploy' group 'deploy' mode '0755' end template "#{node['your_app']['deploy_to']}/shared/database.yml" do source 'database.yml.erb' owner 'deploy' group 'deploy' mode '0644' end
  • 13. Recipe Templates ● chef-repo/cookbooks/your_app_custom/templates/default/database.yml.erb <%= node['your_app']['environment'] %>: adapter: <%= node['your_app']['adapter'] %> database: <%= node['your_app']['database'] %> username: <%= node['your_app']['database_user'] %> <% if node['your_app']['database_password'] %> password: <%= node['your_app']['database_password'] %> <% end %> host: <%= node['your_app']['database_host'] %> encoding: utf8 min_messages: warning
  • 14. Node Attributes ● Application namespace ○ chef-repo/cookbooks/your_app_custom/attributes/default.rb default['your_app']['cap_base'] = '/home/deploy/apps' default['your_app']['deploy_to'] = '/home/deploy/apps/your_app' default['your_app']['environment'] = 'production' default['your_app']['database'] = 'your_app' default['your_app']['adapter'] = 'postgresql' default['your_app']['database_user'] = 'postgres' default['your_app']['database_password'] = (node['postgresql']['password']['postgres'] rescue nil) default['your_app']['database_host'] = 'localhost' default['your_app']['ruby_version'] = '1.9.2-p320'
  • 15. Node Attributes ● For your Node configuration "your_app" : { "environment" : "production", "database" : "your_app", "database_user" : "your_app_db_user", "database_host" : "db1", "hosts" : { "db1" : "nn.nn.nn.nn" } },
  • 16. Define Roles chef-repo/roles/web_server.rb name "web_server" description "web server setup" run_list [ "recipe[build-essential]", "recipe[annoyances]", "recipe[openssl]", "recipe[openssh]", "recipe[sudo]", "recipe[postgresql::client]", "recipe[users_solo::admins]", "recipe[sphinx]", "recipe[imagemagick]", "recipe[nginx]", "recipe[rbenv]", "recipe[postfix]", "recipe[monit]", "recipe[your_app_custom]" ] default_attributes 'build-essential' => { 'compiletime' => true }
  • 17. Node Configuration { "openssh" : { "permit_root_login" : "no", "password_authentication": "no" }, "authorization" : { "sudo" : { "groups" : [ "admin", "sudo" ], "passwordless" : true } }, "rbenv" : { "group_users" : [ "deploy" ] }, "sphinx" : { "use_mysql" : false, "use_postgres" : true }, "your_app" : { "environment" : "production", "database" : "your_app", "database_user" : "your_app_db_user", "database_host" : "db1", "hosts" : { "db1" : "nn.nn.nn.nn" } }, "run_list": [ "role[web_server]" ] }
  • 19. Go! ● bundle exec knife bootstrap -x super_user node_name --template-file=ubuntu-12.04-lts.erb ● bundle exec knife cook super_user@node_name ● Relax!
  • 20. Capistrano - Getting Started ● Add capistrano and capistrano-ext ● Capify ● deploy.rb
  • 21. Capistrano - deploy.rb require 'bundler/capistrano' require 'capistrano/ext/multistage' load 'config/recipes/base' load 'config/recipes/nginx' load 'config/recipes/unicorn' load 'config/recipes/monit' set :default_environment, { 'PATH' => "/opt/rbenv/shims:/opt/rbenv/bin:$PATH", 'RBENV_ROOT' => "/opt/rbenv" } set :bundle_flags, "--deployment --quiet --binstubs --shebang ruby-local-exec" set :use_sudo, false set :application, 'your_app' set :repository, 'git@github.com:you/your_app.git' set :deploy_to, '/home/deploy/apps/your_app' set :deploy_via, :remote_cache
  • 22. Capistrano - deploy.rb set :branch, 'master' set :scm, :git set :target_os, :ubuntu set :maintenance_template_path, File.expand_path(".. /recipes/templates/maintenance.html.erb", __FILE__) default_run_options[:pty] = true ssh_options[:forward_agent] = true namespace :custom do desc 'Create the .rbenv-version file' task :rbenv_version, :roles => :app do run "cd #{release_path} && rbenv local 1.9.2-p320" end end before 'bundle:install', 'custom:rbenv_version'
  • 23. Capistrano - recipes/base.rb def template(from, to) erb = File.read(File.expand_path("../templates/#{from}", __FILE__)) put ERB.new(erb).result(binding), to end def set_default(name, *args, &block) set(name, *args, &block) unless exists?(name) end
  • 24. Capistrano - recipes/monit.rb set_default(:alert_email, "dan@smartlogicsolutions.com") namespace :monit do desc "Setup all Monit configuration" task :setup do unicorn syntax restart end after "deploy:setup", "monit:setup" task(:unicorn, roles: :app) { monit_config "unicorn" } %w[start stop restart syntax].each do |command| desc "Run Monit #{command} script" task command do with_user "deploy" do sudo "service monit #{command}" end end end end
  • 25. Capistrano - recipes/monit.rb def monit_config(name, destination = nil) destination ||= "/etc/monit/conf.d/#{name}.conf" template "monit/#{name}.erb", "/tmp/monit_#{name}" with_user "deploy" do sudo "mv /tmp/monit_#{name} #{destination}" sudo "chown root #{destination}" sudo "chmod 600 #{destination}" end end
  • 26. Capistrano - recipes/nginx.rb namespace :nginx do desc "Setup nginx configuration for this application" task :setup, roles: :web do template "nginx_unicorn.erb", "/tmp/nginx_conf" sudo "mv /tmp/nginx_conf /etc/nginx/sites-enabled/#{application}" sudo "rm -f /etc/nginx/sites-enabled/default" restart end after "deploy:setup", "nginx:setup" %w[start stop restart].each do |command| desc "#{command} nginx" task command, roles: :web do sudo "service nginx #{command}" end end end
  • 27. Capistrano - templates/nginx_unicorn.erb upstream unicorn { server unix:/tmp/unicorn.<%= application %>.sock fail_timeout=0; } server { listen 80 default deferred; server_name your_app_domain.com; root <%= current_path %>/public; if (-f $document_root/system/maintenance.html) { return 503; } error_page 503 @maintenance; location @maintenance { rewrite ^(.*)$ /system/maintenance.html last; break; } location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control 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_set_header X-Forwarded-Proto $scheme; proxy_redirect off; proxy_pass http://unicorn; } error_page 500 502 /500.html; error_page 504 /504.html; client_max_body_size 4G; keepalive_timeout 10; server_tokens off; }
  • 28. Capistrano - recipes/unicorn.rb set_default(:unicorn_user) { user } set_default(:unicorn_pid) { "#{current_path}/tmp/pids/unicorn.pid" } set_default(:unicorn_config) { "#{shared_path}/config/unicorn.rb" } set_default(:unicorn_log) { "#{shared_path}/log/unicorn.log" } set_default(:unicorn_workers) { if rails_env == "production" 10 else 3 end } set_default(:unicorn_timeout, 30)
  • 29. Capistrano - recipes/unicorn.rb namespace :unicorn do desc "Setup Unicorn initializer and app configuration" task :setup, roles: :app do run "mkdir -p #{shared_path}/config" template "unicorn.rb.erb", unicorn_config template "unicorn_init.erb", "/tmp/unicorn_init" run "chmod +x /tmp/unicorn_init" sudo "mv /tmp/unicorn_init /etc/init.d/unicorn_#{application}" sudo "update-rc.d -f unicorn_#{application} defaults" end after "deploy:setup", "unicorn:setup" %w[start stop restart].each do |command| desc "#{command} unicorn" task command, roles: :app do sudo "service unicorn_#{application} #{command}" end after "deploy:#{command}", "unicorn:#{command}" end end
  • 30. Capistrano - templates/unicorn.rb.erb root = "<%= current_path %>" working_directory root pid "#{root}/tmp/pids/unicorn.pid" stderr_path "#{root}/log/unicorn.log" stdout_path "#{root}/log/unicorn.log" listen "/tmp/unicorn.<%= application %>.sock" worker_processes <%= unicorn_workers %> timeout <%= unicorn_timeout %> preload_app true before_exec { |server| ENV['BUNDLE_GEMFILE'] = "#{root}/Gemfile" }
  • 31. Capistrano - templates/unicorn.rb.erb before_fork do |server, worker| # Disconnect since the database connection will not carry over if defined? ActiveRecord::Base ActiveRecord::Base.connection.disconnect! end # Quit the old unicorn process old_pid = "#{server.config[:pid]}.oldbin" if File.exists?(old_pid) && server.pid != old_pid begin Process.kill("QUIT", File.read(old_pid).to_i) rescue Errno::ENOENT, Errno::ESRCH # someone else did our job for us end end end
  • 32. Capistrano - templates/unicorn.rb.erb after_fork do |server, worker| # Start up the database connection again in the worker if defined?(ActiveRecord::Base) ActiveRecord::Base.establish_connection end child_pid = server.config[:pid].sub(".pid", ".#{worker.nr}.pid") system("echo #{Process.pid} > #{child_pid}") end
  • 33. Capistrano - t/monit/unicorn.erb check process <%= application %>_unicorn with pidfile <%= unicorn_pid %> start program = "/etc/init.d/unicorn_<%= application %> start" stop program = "/etc/init.d/unicorn_<%= application %> stop" <% unicorn_workers.times do |n| %> <% pid = unicorn_pid.sub(".pid", ".#{n}.pid") %> check process <%= application %>_unicorn_worker_<%= n %> with pidfile <%= pid %> start program = "/bin/true" stop program = "/usr/bin/test -s <%= pid %> && /bin/kill -QUIT `cat <%= pid %>`" if mem > 200.0 MB for 1 cycles then restart if cpu > 50% for 3 cycles then restart if 5 restarts within 5 cycles then timeout alert <%= alert_email %> only on { pid } if changed pid 2 times within 60 cycles then alert <% end %>
  • 34. Whoa!
  • 35. But really, it is just a bunch of Erb for files you already have
  • 36. Did you see the trick? ● after "deploy:setup", "nginx:setup" So we can... ● cap staging deploy:setup deploy:migrations
  • 38. Ready?!? Here we go! 1. New VM at my_web_app in your .ssh/config 2. Create chef-repo/nodes/my_web_app.json 3. In chef-repo: bundle exec knife bootstrap node_name --template-file=ubuntu-12.04-lts.erb 4. bundle exec knife cook root@my_web_app 5. In app directory: create/edit config/deploy/staging.rb 6. cap staging deploy:setup deploy:migrations 7. Hit the bars
  • 39. Thoughts.... ● Vagrant and VMs are you friend. Rinse and repeat ● It is ok to tweak your Chef stuff and re-cook, but I always like to restart with a fresh VM once I think I'm done ● Capistrano tweaks should be easy to apply, especially with tasks like nginx:setup, unicorn:setup etc. ● Chef issues are harder to debug and more frustrating than Capistrano issues, another reason to put more app specific custom stuff in Capistrano and do standard things in Chef