SlideShare una empresa de Scribd logo
1 de 67
Descargar para leer sin conexión
21 Deployment
Tips in 50 Minutes

  Anthony Burns & Tom Copeland
Railsconf2011 deployment tips_for_slideshare
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)
Railsconf2011 deployment tips_for_slideshare
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

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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 a 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 a 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
 

Último

UiPath Studio Web workshop series - Day 1
UiPath Studio Web workshop series  - Day 1UiPath Studio Web workshop series  - Day 1
UiPath Studio Web workshop series - Day 1DianaGray10
 
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptxEmil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptxNeo4j
 
UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2DianaGray10
 
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedInOutage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedInThousandEyes
 
Patch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updatePatch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updateadam112203
 
20140402 - Smart house demo kit
20140402 - Smart house demo kit20140402 - Smart house demo kit
20140402 - Smart house demo kitJamie (Taka) Wang
 
Novo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNovo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNeo4j
 
Keep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES LiveKeep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES LiveIES VE
 
Top 10 Squarespace Development Companies
Top 10 Squarespace Development CompaniesTop 10 Squarespace Development Companies
Top 10 Squarespace Development CompaniesTopCSSGallery
 
Graphene Quantum Dots-Based Composites for Biomedical Applications
Graphene Quantum Dots-Based Composites for  Biomedical ApplicationsGraphene Quantum Dots-Based Composites for  Biomedical Applications
Graphene Quantum Dots-Based Composites for Biomedical Applicationsnooralam814309
 
Technical SEO for Improved Accessibility WTS FEST
Technical SEO for Improved Accessibility  WTS FESTTechnical SEO for Improved Accessibility  WTS FEST
Technical SEO for Improved Accessibility WTS FESTBillieHyde
 
How to release an Open Source Dataweave Library
How to release an Open Source Dataweave LibraryHow to release an Open Source Dataweave Library
How to release an Open Source Dataweave Libraryshyamraj55
 
Scenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenariosScenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenariosErol GIRAUDY
 
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTSIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTxtailishbaloch
 
Stobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through TokenizationStobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through TokenizationStobox
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightSafe Software
 
Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.IPLOOK Networks
 
Automation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsAutomation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsDianaGray10
 
Where developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is goingWhere developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is goingFrancesco Corti
 
Extra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdfExtra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdfInfopole1
 

Último (20)

UiPath Studio Web workshop series - Day 1
UiPath Studio Web workshop series  - Day 1UiPath Studio Web workshop series  - Day 1
UiPath Studio Web workshop series - Day 1
 
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptxEmil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
Emil Eifrem at GraphSummit Copenhagen 2024 - The Art of the Possible.pptx
 
UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2UiPath Studio Web workshop series - Day 2
UiPath Studio Web workshop series - Day 2
 
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedInOutage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
Outage Analysis: March 5th/6th 2024 Meta, Comcast, and LinkedIn
 
Patch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updatePatch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 update
 
20140402 - Smart house demo kit
20140402 - Smart house demo kit20140402 - Smart house demo kit
20140402 - Smart house demo kit
 
Novo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4jNovo Nordisk's journey in developing an open-source application on Neo4j
Novo Nordisk's journey in developing an open-source application on Neo4j
 
Keep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES LiveKeep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES Live
 
Top 10 Squarespace Development Companies
Top 10 Squarespace Development CompaniesTop 10 Squarespace Development Companies
Top 10 Squarespace Development Companies
 
Graphene Quantum Dots-Based Composites for Biomedical Applications
Graphene Quantum Dots-Based Composites for  Biomedical ApplicationsGraphene Quantum Dots-Based Composites for  Biomedical Applications
Graphene Quantum Dots-Based Composites for Biomedical Applications
 
Technical SEO for Improved Accessibility WTS FEST
Technical SEO for Improved Accessibility  WTS FESTTechnical SEO for Improved Accessibility  WTS FEST
Technical SEO for Improved Accessibility WTS FEST
 
How to release an Open Source Dataweave Library
How to release an Open Source Dataweave LibraryHow to release an Open Source Dataweave Library
How to release an Open Source Dataweave Library
 
Scenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenariosScenario Library et REX Discover industry- and role- based scenarios
Scenario Library et REX Discover industry- and role- based scenarios
 
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENTSIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
SIM INFORMATION SYSTEM: REVOLUTIONIZING DATA MANAGEMENT
 
Stobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through TokenizationStobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
Stobox 4: Revolutionizing Investment in Real-World Assets Through Tokenization
 
The Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and InsightThe Zero-ETL Approach: Enhancing Data Agility and Insight
The Zero-ETL Approach: Enhancing Data Agility and Insight
 
Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.
 
Automation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsAutomation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projects
 
Where developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is goingWhere developers are challenged, what developers want and where DevEx is going
Where developers are challenged, what developers want and where DevEx is going
 
Extra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdfExtra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdf
 

Railsconf2011 deployment tips_for_slideshare

  • 1. 21 Deployment Tips in 50 Minutes Anthony Burns & Tom Copeland
  • 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
  • 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)

Notas del editor

  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