SlideShare a Scribd company logo
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 + ec2
Yros
 
[20180226] I understand webpacker perfectly
[20180226] I understand webpacker perfectly[20180226] I understand webpacker perfectly
[20180226] I understand webpacker perfectly
Yuta Suzuki
 
Front-end tools
Front-end toolsFront-end tools
Front-end tools
Gleb Vinnikov
 
Automation and Ansible
Automation and AnsibleAutomation and Ansible
Automation and Ansible
jtyr
 
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
postrational
 
MeaNstack on Docker
MeaNstack on DockerMeaNstack on Docker
MeaNstack on Docker
Daniel 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 Ansible
Ahmed 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 web
Larry Nung
 
Ansible intro
Ansible introAnsible intro
Ansible intro
Hsi-Kai Wang
 
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 workflow
Riccardo Coppola
 
Capistrano
CapistranoCapistrano
Capistrano
Jason Noble
 
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
Michael H. Oshita
 
Capistrano - automate all the things
Capistrano - automate all the thingsCapistrano - automate all the things
Capistrano - automate all the things
John 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 / Quickstart
Henry Stamerjohann
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with Capistrano
LaunchAny
 
Tdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema RubyTdc 2013 - Ecossistema Ruby
Tdc 2013 - Ecossistema Ruby
Fabio 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

Chef solo the beginning
Chef solo the beginning Chef solo the beginning
Chef solo the beginning
A.K.M. Ahsrafuzzaman
 
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 us
sickill
 
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
Lindsay Holmwood
 
Bangpypers april-meetup-2012
Bangpypers april-meetup-2012Bangpypers april-meetup-2012
Bangpypers april-meetup-2012
Deepak Garg
 
Automating complex infrastructures with Puppet
Automating complex infrastructures with PuppetAutomating complex infrastructures with Puppet
Automating complex infrastructures with Puppet
Kris 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 way
Sylvain 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.js
MongoDB
 
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
MongoDB
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
Arto Artnik
 
Automating Complex Setups with Puppet
Automating Complex Setups with PuppetAutomating Complex Setups with Puppet
Automating Complex Setups with Puppet
Kris Buytaert
 
Chef training - Day2
Chef training - Day2Chef training - Day2
Chef training - Day2
Andriy Samilyak
 
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 2013
Cosimo Streppone
 
MongoDB and Node.js
MongoDB and Node.jsMongoDB and Node.js
MongoDB and Node.js
Norberto Leite
 
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 2012
Carlos 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 Elixir
SmartLogic
 
All Aboard The Stateful Train
All Aboard The Stateful TrainAll Aboard The Stateful Train
All Aboard The Stateful Train
SmartLogic
 
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
SmartLogic
 
Monitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with PrometheusMonitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with Prometheus
SmartLogic
 
Going Multi-Node
Going Multi-NodeGoing Multi-Node
Going Multi-Node
SmartLogic
 
Kubernetes and docker
Kubernetes and dockerKubernetes and docker
Kubernetes and docker
SmartLogic
 
Serializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSerializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara Hacopian
SmartLogic
 
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
SmartLogic
 
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
SmartLogic
 
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 Language
SmartLogic
 
Effective ActiveRecord
Effective ActiveRecordEffective ActiveRecord
Effective ActiveRecord
SmartLogic
 
An Introduction to Reactive Cocoa
An Introduction to Reactive CocoaAn Introduction to Reactive Cocoa
An Introduction to Reactive Cocoa
SmartLogic
 
iOS Development Methodology
iOS Development MethodologyiOS Development Methodology
iOS Development Methodology
SmartLogic
 
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 Code
SmartLogic
 
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
SmartLogic
 
Android Testing: An Overview
Android Testing: An OverviewAndroid Testing: An Overview
Android Testing: An Overview
SmartLogic
 
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
SmartLogic
 
Logstash: Get to know your logs
Logstash: Get to know your logsLogstash: Get to know your logs
Logstash: Get to know your logs
SmartLogic
 

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

Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 

Recently uploaded (20)

Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 

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