SlideShare a Scribd company logo
1 of 67
21 Deployment
Tips in 50 Minutes

  Anthony Burns & Tom Copeland
Vagrant

                 +
• Created by Mitchell Hashimoto
• http://vagrantup.com
• Ruby DSL for provisioning VirtualBox VMs
Vagrant::Config.run do |config|

  config.vm.box = 'dealz-ubuntu-lucid'

  config.vm.forward_port('web', 80, 4567)

  config.vm.host_name('dealz')

  config.vm.network('13.37.33.30')

  config.vm.customize do |vm|

      vm.name = 'dealz'

  end

end
config.network(‘13.37.33.33’)



$ ping 13.37.33.31

PING 13.37.33.31 (13.37.33.31): 56 data bytes

64 bytes from 13.37.33.31: icmp_seq=0 ttl=64 time=0.337 ms

64 bytes from 13.37.33.31: icmp_seq=1 ttl=64 time=0.290 ms

64 bytes from 13.37.33.31: icmp_seq=2 ttl=64 time=0.320 ms
Sadly, Slideshare can’t convert our videos
Vagrant Multi-VM
Vagrant::Config.run do |config|
  config.vm.define :web do |web_config|
    web_config.vm.box = 'dealz-ubuntu-lucid'
    web_config.vm.host_name = 'dealz-web'
    web_config.vm.network('13.37.33.31')
    web_config.vm.customize do |vm|
      vm.name = 'dealz-web'
    end
  end

 config.vm.define :app do |app_config|
   app_config.vm.box = 'dealz-ubuntu-lucid'
   app_config.vm.host_name = 'dealz-app'
   app_config.vm.network('13.37.33.32')
   app_config.vm.customize do |vm|
     vm.name = 'dealz-app'
   end
 end

  config.vm.define :db do |db_config|
    db_config.vm.box = 'dealz-ubuntu-lucid'
    db_config.vm.host_name = 'dealz-db'
    db_config.vm.network('13.37.33.33')
    db_config.vm.customize do |vm|
      vm.name = 'dealz-db'
    end
  end
end
Sadly, Slideshare can’t convert our videos
Capistrano Organization




PittCaleb (flickr)
Sharing Tasks




courosa (flickr)
Deploying with
        RVM

• Created by Wayne Seguin
• http://rvm.beginrescueend.com
• Easy to have multiple Rubies
• Not just for development
Deploying with
         RVM
$:.unshift File.expand_path(ENV[‘RVM_PATH’])
require ‘rvm/capistrano’


set :rvm_ruby_string, ‘ruby-1.9.2-p180’
set :rvm_type, :system
Capistrano gateway




mwschaff (Flickr)
set :gateway, “myserver:4242”
OR
set ssh_options[:4242]
AND
Capistrano 2.6.0 - multiple gateways!
Speeding up with Git

• Technique published by Chris Wanstrath in
  2009
• https://github.com/blog/470-deployment-
  script-spring-cleaning
• Replacement for Capistrano’s deployment
  strategies
Speeding up with Git

• Technique published by Chris Wanstrath in
  2009
• https://github.com/blog/470-deployment-
  script-spring-cleaning
• Replacement for Capistrano’s deployment
  strategies
desc "Set up the current stage for Git-based deployment"

  task :setup, :except => { :no_release => true } do

    setup_command = ["rm -fr #{current_path}"]

    setup_command << "git clone #{repository} #{current_path}"

    setup_command << shared_children.map { |dir| "mkdir -p
#{shared_path}/#{dir}" }

    setup_command << "rvm rvmrc trust #{current_path}"

    setup_command << "gem install bundler --no-rdoc --no-ri"

    run setup_command.join(' && ')

  end
desc "Update the current stage to the latest revision"

  task :update_code, :except => { :no_release => true } do

    update_command = ["git fetch origin && git reset --hard
#{branch}"]

    update_command << "echo #{branch} > #{current_path}/BRANCH"

    update_command << "git rev-parse --verify HEAD --short >
#{current_path}/REVISION"

    run "cd #{current_path} && #{update_command.join(' && ')}"

  end
namespace :rollback do

  task :default do

      code

  end



  task :code, :except => { :no_release => true } do

      set :branch, 'HEAD^'

      deploy

  end

end
Speeding up
        symlinks

• Capistrano defaults to using separate runs
  for each symlink
• Each run is a separate SSH connection
• Consolidate symlinks for a speed boost
desc "Create symlinks to stage-specific configuration files and
shared assets"

  task :symlink, :except => { :no_release => true } do

    command = cleanup_targets.map { |target| "rm -fr #{current_path}/
#{target}" }

    command += release_directories.map { |directory| "mkdir -p
#{directory}" }

    command += shared_symlinks.map { |from, to| "rm -fr
#{current_path}/#{to} && ln -sf #{shared_path}/#{from}
#{current_path}/#{to}" }

    run "cd #{current_path} && #{command.join(" && ")}"

  end
desc "Create symlinks to stage-specific configuration files and
shared assets"

  task :symlink, :except => { :no_release => true } do

    command = cleanup_targets.map { |target| "rm -fr #{current_path}/
#{target}" }

    command += release_directories.map { |directory| "mkdir -p
#{directory}" }

    command += shared_symlinks.map { |from, to| "rm -fr
#{current_path}/#{to} && ln -sf #{shared_path}/#{from}
#{current_path}/#{to}" }

    run "cd #{current_path} && #{command.join(" && ")}"

  end
set :cleanup_targets,        %w(log public/system tmp)

set :release_directories, %w(log tmp)

set :shared_symlinks, {

    'config/database.yml' => 'config/database.yml',

    'config/hoptoad.yml'   => 'config/hoptoad.yml',

    'config/newrelic.yml' => 'config/newrelic.yml',

    'log'                  => 'log',

    'pids'                 => 'tmp/pids',

    'sockets'              => 'tmp/sockets',

    'system'               => 'public/system'

}
Capistrano
                Multistage




mzn37 (flickr)
config/deploy.rb
require 'capistrano/ext/multistage'

set :default_stage, 'qa'




set :application, 'dealz'

set :user,         'dealz'

set :group,        'dealz'

set :use_sudo,     false




set :scm,         :git

set :repository, 'git@github.com:dirtyalpaca/dealz.git'

set :deploy_to,   "/var/#{application}"

set :deploy_via, :remote_cache
config/deploy/production.rb


set :rails_env,    :production



role :web, 'dealz-web'

role :app, 'dealz-app'

role :db,   'dealz-db', :primary => true
config/deploy/qa.rb


set :rails_env,   :qa



server 'dealz-qa', :web, :app, :db, :primary => true
cap deploy


cap qa deploy


cap production deploy
Autoloading from config/deploy


set :stage_dir, “config/stages”


set :default_stage, “staging”
+
Capistrano
bundler/capistrano.rb



after "deploy:update_code", "bundle:install"
set :rake, 'bundle exec rake'
config/deploy.rb



set :bundle_cmd # bundle (/opt/ree/bin/
bundle)
set :bundle_without,   [:development, :test]
Exception Tracking


•   exception_notification
•   newrelic_rpm
•   hoptoad
exception_notification

•   Free and open source

•   https://github.com/rails/exception_notification

•   Simple email notification

•   Modifiable to put in database or message
    queue

•   Flood of emails
newrelic_rpm


• Hosted service (newrelic.com)
• No email flood
• Free and paid plans
• Some delay
Hoptoad

• Hosted service (hoptoadapp.com)
• Specifically for exception tracking
• Free and paid plans
• Excellent UI
Capturing Output
 with Capistrano

 capture(command)
  stream(command)
Capturing Output
namespace :log do

  task :head, :roles => [:app] do

    capture(“tail -n 100 #{shared_path}/log/
#{stage}.log”)

  end



  task :tail, :roles => [:app] do

      stream(“tail -f #{shared_path}/log/#{stage}.log”)

  end

end
Generic Deploy User
Transactions and
   Rollbacks
task :update do
 transaction do
   update_code
   symlink
 end
end
task :update_code, :except => { :no_release => true } do

  on_rollback { run "rm -rf #{release_path}; true" }

  [...]

end
task :symlink, :except => { :no_release => true } do

  on_rollback do

      if previous_release

        run
"rm
‐f
#{current_path};
ln
‐s
#{previous_release}
#{current_path};
true"

        [ ... ]

      end

      [...]

  end

  [...]

end
Capistrano
                   Notifications




whatwhat (flickr)
cap_gun
require 'vendor/plugins/cap_gun/lib/cap_gun'

set :cap_gun_action_mailer_config, {
  :address => "smtp.gmail.com",
  :port => 587,
  :user_name => "[YOUR_USERNAME]@gmail.com",
  :password => "[YOUR_PASSWORD]",
  :authentication => :plain
}

set :cap_gun_email_envelope, {
  :from => "project.deployer@example.com",
  :recipients => %w[joe@example.com, jane@example.com]
}

after "deploy:restart", "cap_gun:email"
Notifying NewRelic RPM


require 'new_relic/recipes'

[ ... ]

after "deploy:update", "newrelic:notice_deployment"
Coming Soon Pages


cap coming_soon:enable
cap coming_soon:disable
Coming Soon Pages
namespace :coming_soon do

  desc "Redirect all requests to the coming soon page"
  task :enable, roles: :web, except: { no_release: true } do
    require 'erb'
    on_rollback { run "rm -f #{shared_path}/system/coming_soon.html" }

    template = File.read(File.expand_path('../../../templates/
coming_soon.html.erb', __FILE__))
    result = ERB.new(template).result(binding)

    put result, "#{shared_path}/system/coming_soon.html", :mode => 0644
  end

  desc "Disable application-wide coming soon page"
  task :disable, :roles => :web, :except => { :no_release => true } do
    run "rm -f #{shared_path}/system/coming_soon.html"
  end

end
Coming Soon Pages


if (-f $document_root/system/coming_soon.html) {
  rewrite ^(.*)$ /system/maintenance.html break;
}
Development
                Database Dumps




j_m_c (flickr)
Log rotation




decade_null (flickr)
CustomLog
"|/usr/bin/rotatelogs
/var/log/access_log 86400"
common
Monitoring
Passenger
require 'rubygems'
gem 'passenger'
require 'phusion_passenger'
require 'phusion_passenger/platform_info'
require 'phusion_passenger/admin_tools/memory_stats'
procs = AdminTools::MemoryStats.new.passenger_processes
raise “ISSUE!” if procs.detect { |p| p.rss > 200*1000 }
Capistrano + Unicorn
set :unicorn_command, 'bundle exec unicorn'
set :unicorn_config, "#{current_path}/config/unicorn.rb"
set :unicorn_pid,     "#{current_path}/tmp/pids/unicorn.pid"

namespace :deploy do
  task :start, :roles => :app, :except => { :no_release => true } do
    run "cd #{current_path} && #{unicorn_command} -c #{unicorn_config} -E
#{rails_env} -D"
  end

  task :stop, :roles => :app, :except => { :no_release => true } do
    run "kill `cat #{unicorn_pid}`"
  end

  task :graceful_stop, :roles => :app, :except => { :no_release => true } do
    run "kill -s QUIT `cat #{unicorn_pid}`"
  end

  task :reload, :roles => :app, :except => { :no_release => true } do
    run "kill -s USR2 `cat #{unicorn_pid}`"
  end

  task :restart, :roles => :app, :except => { :no_release => true } do
    stop
    start
  end
end
Managing Your Schedule
    with Whenever


• Written by Javan Makhmali
• http://github.com/javan/whenever
• Ruby DSL for specifying cron jobs
• Integrates nicely with Capistrano
Managing Your Schedule
     with Whenever


gem ‘whenever’, :require => false
Managing Your Schedule
   with Whenever


      wheneverize .
Managing Your Schedule
   with Whenever
every 3.hours do
  runner "MyModel.some_process"
  rake "my:rake:task"
  command "/usr/bin/my_great_command"
end

every 1.day, :at => '4:30 am' do
  runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end

every :hour do # Many shortcuts
available: :hour, :day, :month, :year, :reboot
  runner "SomeModel.ladeeda"
end

every :sunday, :at => '12pm' do # Use any day of the week
or :weekend, :weekday
  runner "Task.do_something_great"
end

every '0 0 27-31 * *' do
  command "echo 'you can use raw cron sytax too'"
end

                    (from the GitHub wiki)
Managing Your Schedule
     with Whenever


set :whenever_command, ‘bundle exec whenever’
require ‘whenever/capistrano’




                (from the GitHub wiki)
ssh-agent




andertoons-cartoons(flickr)
A Gotcha




kayaker1204 (flickr)
Shameless Plug
Questions
tom.copeland@livingsocial.com
anthony.burns@livingsocial.com
         @tcopeland
         @dirtyalpaca

More Related Content

What's hot

VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareCosimo Streppone
 
Http capturing
Http capturingHttp capturing
Http capturingEric Ahn
 
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...Willian Molinari
 
Fabric workshop(1) - (MOSG)
Fabric workshop(1) - (MOSG)Fabric workshop(1) - (MOSG)
Fabric workshop(1) - (MOSG)Soshi Nemoto
 
Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteBram Vogelaar
 
Py conkr 20150829_docker-python
Py conkr 20150829_docker-pythonPy conkr 20150829_docker-python
Py conkr 20150829_docker-pythonEric Ahn
 
Creating Reusable Puppet Profiles
Creating Reusable Puppet ProfilesCreating Reusable Puppet Profiles
Creating Reusable Puppet ProfilesBram Vogelaar
 
PuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetPuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetWalter Heck
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)Robert Swisher
 
Hacking ansible
Hacking ansibleHacking ansible
Hacking ansiblebcoca
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stackBram Vogelaar
 
Testing your infrastructure with litmus
Testing your infrastructure with litmusTesting your infrastructure with litmus
Testing your infrastructure with litmusBram Vogelaar
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnAppWalter Heck
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidenceJohn Congdon
 
Autoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadAutoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadBram Vogelaar
 
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
 
More tips n tricks
More tips n tricksMore tips n tricks
More tips n tricksbcoca
 
Observability with Consul Connect
Observability with Consul ConnectObservability with Consul Connect
Observability with Consul ConnectBram Vogelaar
 

What's hot (20)

VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera Software
 
Http capturing
Http capturingHttp capturing
Http capturing
 
Ubic
UbicUbic
Ubic
 
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
How we used ruby to build locaweb's cloud (http://presentations.pothix.com/ru...
 
Fabric workshop(1) - (MOSG)
Fabric workshop(1) - (MOSG)Fabric workshop(1) - (MOSG)
Fabric workshop(1) - (MOSG)
 
Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
 
Py conkr 20150829_docker-python
Py conkr 20150829_docker-pythonPy conkr 20150829_docker-python
Py conkr 20150829_docker-python
 
kubernetes practice
kubernetes practicekubernetes practice
kubernetes practice
 
Creating Reusable Puppet Profiles
Creating Reusable Puppet ProfilesCreating Reusable Puppet Profiles
Creating Reusable Puppet Profiles
 
PuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetPuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of Puppet
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
Hacking ansible
Hacking ansibleHacking ansible
Hacking ansible
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
 
Testing your infrastructure with litmus
Testing your infrastructure with litmusTesting your infrastructure with litmus
Testing your infrastructure with litmus
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
Release with confidence
Release with confidenceRelease with confidence
Release with confidence
 
Autoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadAutoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomad
 
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
 
More tips n tricks
More tips n tricksMore tips n tricks
More tips n tricks
 
Observability with Consul Connect
Observability with Consul ConnectObservability with Consul Connect
Observability with Consul Connect
 

Similar to Railsconf2011 deployment tips_for_slideshare

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
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto Artnik
 
Deploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoDeploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoAlmir Mendes
 
Practical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppPractical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppSmartLogic
 
Control your deployments with Capistrano
Control your deployments with CapistranoControl your deployments with Capistrano
Control your deployments with CapistranoRamazan K
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf Conference
 
Continuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierContinuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierCarlos Sanchez
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with CapistranoLaunchAny
 
Cutting through the fog of cloud
Cutting through the fog of cloudCutting through the fog of cloud
Cutting through the fog of cloudKyle Rames
 
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é
 
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Омские ИТ-субботники
 
X64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newX64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newYiwei Ma
 

Similar to Railsconf2011 deployment tips_for_slideshare (20)

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
 
EC2
EC2EC2
EC2
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Deploying Rails Applications with Capistrano
Deploying Rails Applications with CapistranoDeploying Rails Applications with Capistrano
Deploying Rails Applications with Capistrano
 
Practical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails AppPractical Chef and Capistrano for Your Rails App
Practical Chef and Capistrano for Your Rails App
 
Control your deployments with Capistrano
Control your deployments with CapistranoControl your deployments with Capistrano
Control your deployments with Capistrano
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
 
Capistrano2
Capistrano2Capistrano2
Capistrano2
 
Continuous Delivery: The Next Frontier
Continuous Delivery: The Next FrontierContinuous Delivery: The Next Frontier
Continuous Delivery: The Next Frontier
 
Puppet Camp 2012
Puppet Camp 2012Puppet Camp 2012
Puppet Camp 2012
 
Capistrano
CapistranoCapistrano
Capistrano
 
Getting Started with Capistrano
Getting Started with CapistranoGetting Started with Capistrano
Getting Started with Capistrano
 
Cutting through the fog of cloud
Cutting through the fog of cloudCutting through the fog of cloud
Cutting through the fog of cloud
 
Ubic-public
Ubic-publicUbic-public
Ubic-public
 
Capistrano Overview
Capistrano OverviewCapistrano Overview
Capistrano Overview
 
Cooking with Chef
Cooking with ChefCooking with Chef
Cooking with Chef
 
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
 
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
 
X64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 newX64服务器 lnmp服务器部署标准 new
X64服务器 lnmp服务器部署标准 new
 

Recently uploaded

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
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
 
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
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
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
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 

Recently uploaded (20)

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
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
 
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...
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
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
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 

Railsconf2011 deployment tips_for_slideshare

  • 1. 21 Deployment Tips in 50 Minutes Anthony Burns & Tom Copeland
  • 2.
  • 3. Vagrant + • Created by Mitchell Hashimoto • http://vagrantup.com • Ruby DSL for provisioning VirtualBox VMs
  • 4. Vagrant::Config.run do |config| config.vm.box = 'dealz-ubuntu-lucid' config.vm.forward_port('web', 80, 4567) config.vm.host_name('dealz') config.vm.network('13.37.33.30') config.vm.customize do |vm| vm.name = 'dealz' end end
  • 5. config.network(‘13.37.33.33’) $ ping 13.37.33.31 PING 13.37.33.31 (13.37.33.31): 56 data bytes 64 bytes from 13.37.33.31: icmp_seq=0 ttl=64 time=0.337 ms 64 bytes from 13.37.33.31: icmp_seq=1 ttl=64 time=0.290 ms 64 bytes from 13.37.33.31: icmp_seq=2 ttl=64 time=0.320 ms
  • 6. Sadly, Slideshare can’t convert our videos
  • 8. Vagrant::Config.run do |config| config.vm.define :web do |web_config| web_config.vm.box = 'dealz-ubuntu-lucid' web_config.vm.host_name = 'dealz-web' web_config.vm.network('13.37.33.31') web_config.vm.customize do |vm| vm.name = 'dealz-web' end end config.vm.define :app do |app_config| app_config.vm.box = 'dealz-ubuntu-lucid' app_config.vm.host_name = 'dealz-app' app_config.vm.network('13.37.33.32') app_config.vm.customize do |vm| vm.name = 'dealz-app' end end config.vm.define :db do |db_config| db_config.vm.box = 'dealz-ubuntu-lucid' db_config.vm.host_name = 'dealz-db' db_config.vm.network('13.37.33.33') db_config.vm.customize do |vm| vm.name = 'dealz-db' end end end
  • 9. Sadly, Slideshare can’t convert our videos
  • 11.
  • 13. Deploying with RVM • Created by Wayne Seguin • http://rvm.beginrescueend.com • Easy to have multiple Rubies • Not just for development
  • 14. Deploying with RVM $:.unshift File.expand_path(ENV[‘RVM_PATH’]) require ‘rvm/capistrano’ set :rvm_ruby_string, ‘ruby-1.9.2-p180’ set :rvm_type, :system
  • 16. set :gateway, “myserver:4242” OR set ssh_options[:4242] AND Capistrano 2.6.0 - multiple gateways!
  • 17. Speeding up with Git • Technique published by Chris Wanstrath in 2009 • https://github.com/blog/470-deployment- script-spring-cleaning • Replacement for Capistrano’s deployment strategies
  • 18. Speeding up with Git • Technique published by Chris Wanstrath in 2009 • https://github.com/blog/470-deployment- script-spring-cleaning • Replacement for Capistrano’s deployment strategies
  • 19. desc "Set up the current stage for Git-based deployment" task :setup, :except => { :no_release => true } do setup_command = ["rm -fr #{current_path}"] setup_command << "git clone #{repository} #{current_path}" setup_command << shared_children.map { |dir| "mkdir -p #{shared_path}/#{dir}" } setup_command << "rvm rvmrc trust #{current_path}" setup_command << "gem install bundler --no-rdoc --no-ri" run setup_command.join(' && ') end
  • 20. desc "Update the current stage to the latest revision" task :update_code, :except => { :no_release => true } do update_command = ["git fetch origin && git reset --hard #{branch}"] update_command << "echo #{branch} > #{current_path}/BRANCH" update_command << "git rev-parse --verify HEAD --short > #{current_path}/REVISION" run "cd #{current_path} && #{update_command.join(' && ')}" end
  • 21. namespace :rollback do task :default do code end task :code, :except => { :no_release => true } do set :branch, 'HEAD^' deploy end end
  • 22. Speeding up symlinks • Capistrano defaults to using separate runs for each symlink • Each run is a separate SSH connection • Consolidate symlinks for a speed boost
  • 23. desc "Create symlinks to stage-specific configuration files and shared assets" task :symlink, :except => { :no_release => true } do command = cleanup_targets.map { |target| "rm -fr #{current_path}/ #{target}" } command += release_directories.map { |directory| "mkdir -p #{directory}" } command += shared_symlinks.map { |from, to| "rm -fr #{current_path}/#{to} && ln -sf #{shared_path}/#{from} #{current_path}/#{to}" } run "cd #{current_path} && #{command.join(" && ")}" end
  • 24. desc "Create symlinks to stage-specific configuration files and shared assets" task :symlink, :except => { :no_release => true } do command = cleanup_targets.map { |target| "rm -fr #{current_path}/ #{target}" } command += release_directories.map { |directory| "mkdir -p #{directory}" } command += shared_symlinks.map { |from, to| "rm -fr #{current_path}/#{to} && ln -sf #{shared_path}/#{from} #{current_path}/#{to}" } run "cd #{current_path} && #{command.join(" && ")}" end
  • 25. set :cleanup_targets, %w(log public/system tmp) set :release_directories, %w(log tmp) set :shared_symlinks, { 'config/database.yml' => 'config/database.yml', 'config/hoptoad.yml' => 'config/hoptoad.yml', 'config/newrelic.yml' => 'config/newrelic.yml', 'log' => 'log', 'pids' => 'tmp/pids', 'sockets' => 'tmp/sockets', 'system' => 'public/system' }
  • 26. Capistrano Multistage mzn37 (flickr)
  • 27. config/deploy.rb require 'capistrano/ext/multistage' set :default_stage, 'qa' set :application, 'dealz' set :user, 'dealz' set :group, 'dealz' set :use_sudo, false set :scm, :git set :repository, 'git@github.com:dirtyalpaca/dealz.git' set :deploy_to, "/var/#{application}" set :deploy_via, :remote_cache
  • 28. config/deploy/production.rb set :rails_env, :production role :web, 'dealz-web' role :app, 'dealz-app' role :db, 'dealz-db', :primary => true
  • 29. config/deploy/qa.rb set :rails_env, :qa server 'dealz-qa', :web, :app, :db, :primary => true
  • 30. cap deploy cap qa deploy cap production deploy
  • 31. Autoloading from config/deploy set :stage_dir, “config/stages” set :default_stage, “staging”
  • 34. config/deploy.rb set :bundle_cmd # bundle (/opt/ree/bin/ bundle) set :bundle_without, [:development, :test]
  • 35. Exception Tracking • exception_notification • newrelic_rpm • hoptoad
  • 36. exception_notification • Free and open source • https://github.com/rails/exception_notification • Simple email notification • Modifiable to put in database or message queue • Flood of emails
  • 37. newrelic_rpm • Hosted service (newrelic.com) • No email flood • Free and paid plans • Some delay
  • 38. Hoptoad • Hosted service (hoptoadapp.com) • Specifically for exception tracking • Free and paid plans • Excellent UI
  • 39. Capturing Output with Capistrano capture(command) stream(command)
  • 40. Capturing Output namespace :log do task :head, :roles => [:app] do capture(“tail -n 100 #{shared_path}/log/ #{stage}.log”) end task :tail, :roles => [:app] do stream(“tail -f #{shared_path}/log/#{stage}.log”) end end
  • 42. Transactions and Rollbacks
  • 43. task :update do transaction do update_code symlink end end
  • 44. task :update_code, :except => { :no_release => true } do on_rollback { run "rm -rf #{release_path}; true" } [...] end
  • 45. task :symlink, :except => { :no_release => true } do on_rollback do if previous_release run
"rm
‐f
#{current_path};
ln
‐s
#{previous_release}
#{current_path};
true" [ ... ] end [...] end [...] end
  • 46. Capistrano Notifications whatwhat (flickr)
  • 47. cap_gun require 'vendor/plugins/cap_gun/lib/cap_gun' set :cap_gun_action_mailer_config, { :address => "smtp.gmail.com", :port => 587, :user_name => "[YOUR_USERNAME]@gmail.com", :password => "[YOUR_PASSWORD]", :authentication => :plain } set :cap_gun_email_envelope, { :from => "project.deployer@example.com", :recipients => %w[joe@example.com, jane@example.com] } after "deploy:restart", "cap_gun:email"
  • 48. Notifying NewRelic RPM require 'new_relic/recipes' [ ... ] after "deploy:update", "newrelic:notice_deployment"
  • 49. Coming Soon Pages cap coming_soon:enable cap coming_soon:disable
  • 50. Coming Soon Pages namespace :coming_soon do desc "Redirect all requests to the coming soon page" task :enable, roles: :web, except: { no_release: true } do require 'erb' on_rollback { run "rm -f #{shared_path}/system/coming_soon.html" } template = File.read(File.expand_path('../../../templates/ coming_soon.html.erb', __FILE__)) result = ERB.new(template).result(binding) put result, "#{shared_path}/system/coming_soon.html", :mode => 0644 end desc "Disable application-wide coming soon page" task :disable, :roles => :web, :except => { :no_release => true } do run "rm -f #{shared_path}/system/coming_soon.html" end end
  • 51. Coming Soon Pages if (-f $document_root/system/coming_soon.html) { rewrite ^(.*)$ /system/maintenance.html break; }
  • 52. Development Database Dumps j_m_c (flickr)
  • 56. require 'rubygems' gem 'passenger' require 'phusion_passenger' require 'phusion_passenger/platform_info' require 'phusion_passenger/admin_tools/memory_stats' procs = AdminTools::MemoryStats.new.passenger_processes raise “ISSUE!” if procs.detect { |p| p.rss > 200*1000 }
  • 57. Capistrano + Unicorn set :unicorn_command, 'bundle exec unicorn' set :unicorn_config, "#{current_path}/config/unicorn.rb" set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid" namespace :deploy do task :start, :roles => :app, :except => { :no_release => true } do run "cd #{current_path} && #{unicorn_command} -c #{unicorn_config} -E #{rails_env} -D" end task :stop, :roles => :app, :except => { :no_release => true } do run "kill `cat #{unicorn_pid}`" end task :graceful_stop, :roles => :app, :except => { :no_release => true } do run "kill -s QUIT `cat #{unicorn_pid}`" end task :reload, :roles => :app, :except => { :no_release => true } do run "kill -s USR2 `cat #{unicorn_pid}`" end task :restart, :roles => :app, :except => { :no_release => true } do stop start end end
  • 58. Managing Your Schedule with Whenever • Written by Javan Makhmali • http://github.com/javan/whenever • Ruby DSL for specifying cron jobs • Integrates nicely with Capistrano
  • 59. Managing Your Schedule with Whenever gem ‘whenever’, :require => false
  • 60. Managing Your Schedule with Whenever wheneverize .
  • 61. Managing Your Schedule with Whenever every 3.hours do runner "MyModel.some_process" rake "my:rake:task" command "/usr/bin/my_great_command" end every 1.day, :at => '4:30 am' do runner "MyModel.task_to_run_at_four_thirty_in_the_morning" end every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot runner "SomeModel.ladeeda" end every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday runner "Task.do_something_great" end every '0 0 27-31 * *' do command "echo 'you can use raw cron sytax too'" end (from the GitHub wiki)
  • 62. Managing Your Schedule with Whenever set :whenever_command, ‘bundle exec whenever’ require ‘whenever/capistrano’ (from the GitHub wiki)

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. tunnel from port 4567 to port 80 on the VM\ntunnel from port 2222 to port 22 on the VM\nfolder in which vagrantfile exists is shared\n
  5. tunnel from port 4567 to port 80 on the VM\ntunnel from port 2222 to port 22 on the VM\nfolder in which vagrantfile exists is shared\n
  6. \n
  7. - Use case for testing system configuration\n- Provisioning script development (Puppet, Chef, etc.)\n- Networked so they can talk\n
  8. \n
  9. \n
  10. lib/deploy/\nhooks in config/deploy.rb\n\n\n
  11. \n
  12. submodule or gem? 50/50, maybe submodule\n
  13. \n
  14. \n
  15. many servers, only one accepting connections\n
  16. cap 2.6.0 released may 4\n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. deploy to multiple environments\nintegration/qa/production\n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. if you have qa/performance blocks in your gemfile, set :bundle_without\n
  34. if you have qa/performance blocks in your gemfile, set :bundle_without\n
  35. - show of hands - who&apos;s using hoptoad?\n - exception_notifier - pros: easy, simple, can modify to put in DB or on msg queue cons: flood o&apos; email\n - can use new relic - pros: good display, no email flood, (? how does dev get notified?) cons: some delay, $$\n - hoptoad\n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. individual accounts: logs get wrong permissions, daemons get started as wrong users, you need a generic account for init scripts anyway\ngoal is to avoid situation where people have to ssh in\n
  42. when task fails, capistrano checks for rollback hooks\n
  43. &amp;#x201C;cap deploy&amp;#x201D; consists of update and restart\nupdate has two subtasks which it runs in a txn\n
  44. so you can see how you can write your own tasks that use txns and clean up after themselves\n
  45. so you can see how you can write your own tasks that use txns and clean up after themselves\n
  46. tinder - campfire notify, but don&amp;#x2019;t notify to &amp;#x2018;human&amp;#x2019; chatrooms\ncap_gun - email, includes diff\n\n\n
  47. \n
  48. can also set : newrelic_revision, :newrelic_changelog\non the newrelic site appears as a line in the graph, also a list of recent deployments\n
  49. \n
  50. \n
  51. \n
  52. not just because of size, but also sensitive data\nautomate it\ndump from slave, normalize sensitive data (passwords)\ndecrease size by keeping recent or by partitioning\n
  53. apache-specific\n
  54. can use either time interval or size\nwith nginx, mv log, kill -USR1 4242, sleep 5, zip log or whatever\n
  55. monitoring passenger memory usage\n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. private keys with passphrases without hassle\nlaunchd - org.openbsd.ssh-agent.plist\n&amp;#x201C;ForwardAgent yes&amp;#x201D; in your .ssh/config\n
  64. too many keys in ssh-agent results in server rejection (MaxAuthTries 6, maximum number of authentication attempts permitted per connection)\nssh-add -l to list, ssh-add -d filename to remove\n
  65. \n
  66. \n
  67. \n