Skip to content

Instantly share code, notes, and snippets.

@joaofraga
Created May 26, 2014 17:34
Show Gist options
  • Save joaofraga/cb11c36e42dae74ef538 to your computer and use it in GitHub Desktop.
Save joaofraga/cb11c36e42dae74ef538 to your computer and use it in GitHub Desktop.
New server deploy configuration
# config valid only for Capistrano 3.1
lock '3.1.0'
set :application, 'samplewebsite.com'
# set :deploy_via, :copy
set :deploy_to, "/var/apps/#{fetch(:application)}"
set :checkout, "export"
# default_run_options[:pty] = true
set :use_sudo, false
set :repo_url, 'git@repository.git'
# Default branch is :master
# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }
# Default deploy_to directory is /var/www/my_app
# Default value for :scm is :git
# set :scm, :git
# Default value for :format is :pretty
# set :format, :pretty
# Default value for :log_level is :debug
# set :log_level, :debug
# Default value for :pty is false
# set :pty, true
# Default value for :linked_files is []
set :linked_files, %w{config/database.yml}
# Default value for linked_dirs is []
set :linked_dirs, fetch(:linked_dirs) + %w{public/quotes public/uploads}
# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
# Default value for keep_releases is 5
# set :keep_releases, 5
set :unicorn_config, "config/unicorn.rb"
set :unicorn_pid, "/tmp/unicorn.samplewebsite.com.pid"
namespace :deploy do
desc 'Start application'
task :start do
on roles(:app) do
within current_path do
with rails_env: fetch(:rails_env) do
execute :bundle, "exec unicorn_rails -c #{fetch(:unicorn_config)} -D"
end
end
# run "cd #{current_path} && if [ ! -d tmp/pids ]; then rm -rf tmp/pids; fi"
# run "cd #{current_path} && bundle exec unicorn_rails -c config/unicorn.rb -D -E production"
end
end
desc 'Stop application'
task :stop do
on roles(:app) do
if test("[ -f #{fetch(:unicorn_pid)} ]")
execute :kill, capture(:cat, fetch(:unicorn_pid))
# run "kill -s QUIT `cat /tmp/unicorn.samplewebsite.com.pid`"
end
end
end
desc 'Reload unicorn without stop application'
task :reload do
on roles(:app) do
if test("[ -f #{fetch(:unicorn_pid)} ]")
execute :kill, '-s USR2', capture(:cat, fetch(:unicorn_pid))
else
error 'Unicorn process not running'
end
end
end
desc 'Restart Unicorn'
task :restart
before :restart, :stop
before :restart, :start
after :publishing, :reload
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
end
# config/deploy/production.rb
# Simple Role Syntax
# ==================
# Supports bulk-adding hosts to roles, the primary
# server in each group is considered to be the first
# unless any hosts have the primary property set.
# Don't declare `role :all`, it's a meta role
# role :app, %w{deploy@samplewebsite.com}
# role :web, %w{deploy@samplewebsite.com}
# role :db, %w{deploy@samplewebsite.com}
# Extended Server Syntax
# ======================
# This can be used to drop a more detailed server
# definition into the server list. The second argument
# something that quacks like a hash can be used to set
# extended properties on the server.
server 'samplewebsite.me', user: 'deploy', roles: %w{web app}, ssh_options: {
user: 'deploy', # overrides user setting above
forward_agent: false,
auth_methods: %w(password),
password: 'YOUR_PASSWORD'
}
# you can set custom ssh options
# it's possible to pass any option but you need to keep in mind that net/ssh understand limited list of options
# you can see them in [net/ssh documentation](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start)
# set it globally
# set :ssh_options, {
# keys: %w(/home/deploy/.ssh/id_rsa),
# forward_agent: false,
# auth_methods: %w(password)
# }
set :rails_env, "production"
# and/or per server
# server 'example.com',
# user: 'user_name',
# roles: %w{web app},
# ssh_options: {
# user: 'user_name', # overrides user setting above
# keys: %w(/home/user_name/.ssh/id_rsa),
# forward_agent: false,
# auth_methods: %w(publickey password)
# # password: 'please use keys'
# }
# setting per server overrides global ssh_options
# /etc/nginx/sites-avaible/samplewebsite.com
upstream samplewebsite {
server unix:/tmp/samplewebsite.com.socket fail_timeout=0;
}
server {
# enable one of the following if you're on Linux or FreeBSD
# listen 80 default deferred; # for Linux
# listen 80 default accept_filter=httpready; # for FreeBSD
# If you have IPv6, you'll likely want to have two separate listeners.
# One on IPv4 only (the default), and another on IPv6 only instead
# of a single dual-stack listener. A dual-stack listener will make
# for ugly IPv4 addresses in $remote_addr (e.g ":ffff:10.0.0.1"
# instead of just "10.0.0.1") and potentially trigger bugs in
# some software.
# listen [::]:80 ipv6only=on; # deferred or accept_filter recommended
client_max_body_size 4G;
server_name samplewebsite.com;
# ~2 seconds is often enough for most folks to parse HTML/CSS and
# retrieve needed images/icons/frames, connections are cheap in
# nginx so increasing this is generally safe...
keepalive_timeout 5;
# path for static files
root /var/apps/samplewebsite.com/current/public;
# Prefer to serve static files directly from nginx to avoid unnecessary
# data copies from the application server.
#
# try_files directive appeared in in nginx 0.7.27 and has stabilized
# over time. Older versions of nginx (e.g. 0.6.x) requires
# "if (!-f $request_filename)" which was less efficient:
# http://bogomips.org/unicorn.git/tree/examples/nginx.conf?id=v3.3.1#n127
try_files $uri/index.html $uri.html $uri @app;
location @app {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if you forward HTTPS traffic to unicorn,
# this helps Rack set the proper URL scheme for doing redirects:
# proxy_set_header X-Forwarded-Proto $scheme;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll/streaming. It's also safe to set if you're using
# only serving fast clients with Unicorn + nginx, but not slow
# clients. You normally want nginx to buffer responses to slow
# clients, even with Rails 3.1 streaming because otherwise a slow
# client can become a bottleneck of Unicorn.
#
# The Rack application may also set "X-Accel-Buffering (yes|no)"
# in the response headers do disable/enable buffering on a
# per-response basis.
# proxy_buffering off;
proxy_pass http://samplewebsite;
}
}
# config/unicorn.rb
# Set environment to development unless something else is specified
env = ENV["RAILS_ENV"].to_sym || :development
# Set base app path
base_path = {
production: "/var/apps/samplewebsite.com",
development: "/var/www/samplewebsite.com"
}
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
worker_processes 4
# listen on both a Unix domain socket and a TCP port,
# we use a shorter backlog for quicker failover when busy
listen "/tmp/samplewebsite.com.socket", :backlog => 64
# Load app into the master before forking workers for super-fast
# worker spawn times
preload_app true
# nuke workers after 30 seconds (60 is the default)
timeout 30
pid "/tmp/unicorn.samplewebsite.com.pid"
if env != :development
working_directory "#{base_path[env]}/current"
shared_path = "#{base_path[env]}/shared"
stderr_path "#{shared_path}/log/unicorn.stderr.log"
stdout_path "#{shared_path}/log/unicorn.stdout.log"
end
# http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
if GC.respond_to?(:copy_on_write_friendly=)
GC.copy_on_write_friendly = true
end
before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
##
# When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
# immediately start loading up a new version of itself (loaded with a new
# version of our app). When this new Unicorn is completely loaded
# it will begin spawning workers. The first worker spawned will check to
# see if an .oldbin pidfile exists. If so, this means we've just booted up
# a new Unicorn and need to tell the old one that it can now die. To do so
# we send it a QUIT.
#
# Using this method we get 0 downtime deploys.
old_pid = "/tmp/unicorn.samplewebsite.com.pid.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
after_fork do |server, worker|
# Unicorn master loads the app then forks off workers - because of the way
# Unix forking works, we need to make sure we aren't using any of the parent's
# sockets, e.g. db connection
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
# Redis and Memcached would go here but their connections are established
# on demand, so the master never opens a socket
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment