- Replace all instances of app_name with the name of your application in lower letters
Created
July 20, 2012 22:49
-
-
Save eoy/3153735 to your computer and use it in GitHub Desktop.
Eoy's Server/Deploy Setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "bundler/capistrano" | |
set :whenever_command, "bundle exec whenever" | |
require 'whenever/capistrano' | |
server "123.456.789.10", :web, :app, :db, primary: true | |
set :application, "app_name" | |
set :user, "deployer" | |
set :deploy_to, "/home/#{user}/apps/#{application}" | |
set :deploy_via, :remote_cache | |
set :use_sudo, false | |
set :scm, "git" | |
set :repository, "git@github.com:eoy/#{application}.git" | |
set :branch, "master" | |
default_run_options[:pty] = true | |
ssh_options[:forward_agent] = true | |
after "deploy", "deploy:uploads:symlink" # keep only the last 5 releases | |
after "deploy:uploads:symlink", "deploy:cleanup" | |
namespace :deploy do | |
# OLD STUFF FOR NON 0-DOWNTIME DEPLOYS ### DON'T DELETE | |
# %w[start stop restart].each do |command| | |
# desc "#{command} unicorn server" | |
# task command, roles: :app, except: {no_release: true} do | |
# run "/etc/init.d/unicorn_#{application} #{command}" | |
# end | |
# end | |
desc "Zero-downtime restart of Unicorn" | |
task :restart, :except => { :no_release => true } do | |
run "kill -s USR2 `cat /tmp/unicorn.app_name.pid`" | |
end | |
desc "Start unicorn" | |
task :start, :except => { :no_release => true } do | |
run "/etc/init.d/unicorn_#{application} start" | |
end | |
desc "Stop unicorn" | |
task :stop, :except => { :no_release => true } do | |
run "kill -s QUIT `cat /tmp/unicorn.app_name.pid`" | |
end | |
desc "Upgrade code and restart unicorn server" | |
task :upgrade, :roles => :app, :except => { :no_release => true } do | |
run "/etc/init.d/unicorn_#{application} upgrade" | |
end | |
desc "Remote console" | |
task :console, :roles => :app do | |
env = "production" | |
server = find_servers(:roles => [:app]).first | |
run_with_tty server, %W( ./script/rails console #{env} ) | |
end | |
def run_with_tty(server, cmd) | |
# looks like total pizdets | |
command = [] | |
command += %W( ssh -t #{gateway} -l #{self[:gateway_user] || self[:user]} ) if self[:gateway] | |
command += %W( ssh -t ) | |
command += %W( -p #{server.port}) if server.port | |
command += %W( -l #{user} #{server.host} ) | |
command += %W( cd #{current_path} ) | |
# have to escape this once if running via double ssh | |
command += [self[:gateway] ? '\&\&' : '&&'] | |
command += Array(cmd) | |
system *command | |
end | |
task :setup_config, roles: :app do | |
sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/sites-enabled/#{application}" | |
sudo "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{application}" | |
run "mkdir -p #{shared_path}/config" | |
put File.read("config/database.example.yml"), "#{shared_path}/config/database.yml" | |
puts "Now edit the config files in #{shared_path}." | |
end | |
after "deploy:setup", "deploy:setup_config" | |
task :symlink_config, roles: :app do | |
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml" | |
end | |
after "deploy:finalize_update", "deploy:symlink_config" | |
desc "Make sure local git is in sync with remote." | |
task :check_revision, roles: :web do | |
unless `git rev-parse HEAD` == `git rev-parse origin/master` | |
puts "WARNING: HEAD is not the same as origin/master" | |
puts "Run `git push` to sync changes." | |
exit | |
end | |
end | |
namespace :uploads do | |
desc "Link uploads from shared to current" | |
task :symlink do | |
run "cd #{current_path}/public; rm -rf uploads; ln -s #{shared_path}/uploads ." | |
end | |
end | |
namespace :ts do | |
%w[index start stop restart reindex rebuild].each do |command| | |
desc "#{command} Thinking Sphinx server" | |
task command do | |
run "cd #{current_path}; RAILS_ENV=production rake ts:#{command}" | |
end | |
end | |
end | |
namespace :bundle do | |
%w[install update clean outdated].each do |command| | |
desc "Sending << #{command} >> through bundler." | |
task command do | |
run "cd #{current_path}; RAILS_ENV=production bundle #{command}" | |
end | |
end | |
end | |
namespace :db do | |
task :seed do | |
run "cd #{current_path}; RAILS_ENV=production rake db:seed" | |
end | |
task :migrate do | |
run "cd #{current_path}; RAILS_ENV=production rake db:migrate" | |
end | |
end | |
# Delayed Job commands | |
namespace :dj do | |
%w[start stop].each do |command| | |
desc "#{command} Delayed_job worker" | |
task command, roles: :app do | |
run "cd #{current_path}; RAILS_ENV=production script/delayed_job #{command}" | |
end | |
end | |
end | |
namespace :assets do | |
task :precompile, :roles => :web, :except => { :no_release => true } do | |
from = source.next_revision(current_revision) | |
if capture("cd #{latest_release} && #{source.local.log(from)} vendor/assets/ app/assets/ | wc -l").to_i > 0 | |
run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile} | |
else | |
logger.info "Skipping asset pre-compilation because there were no asset changes" | |
end | |
end | |
end | |
#before "deploy", "deploy:check_revision" | |
end | |
namespace :log do | |
desc "A pinch of tail" | |
task :tailf, :roles => :app do | |
run "tail -n 10000 -f #{shared_path}/log/#{rails_env}.log" do |channel, stream, data| | |
puts "#{data}" | |
break if stream == :err | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
upstream app_name { | |
server unix:/tmp/unicorn.app_name.sock fail_timeout=0; | |
} | |
server { | |
listen 80 default deferred; | |
server_name _; | |
root /home/deployer/apps/app_name/current/public; | |
location ^~ /assets/ { | |
gzip_static on; | |
expires max; | |
add_header Cache-Control public; | |
} | |
# Favicon | |
location ~* \.ico$ { | |
expires 1w; | |
access_log off; | |
add_header Cache-Control "public"; | |
} | |
# Media: images, video, audio, HTC, WebFonts | |
location ~* \.(?:jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|eot|mp4|ogg|ogv|webm)$ { | |
expires 1M; | |
access_log off; | |
add_header Cache-Control "public"; | |
} | |
try_files $uri/index.html $uri @unicorn; | |
location @unicorn { | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header Host $http_host; | |
proxy_redirect off; | |
proxy_pass http://app_name; | |
#if ($request_uri ~* "\.(ico|css|js|gif|jpe?g|png)\?[0-9]+$") { | |
# expires max; | |
# break; | |
#} | |
} | |
error_page 500 502 503 504 /500.html; | |
client_max_body_size 4G; | |
keepalive_timeout 10; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root = "/home/deployer/apps/app_name/current" | |
working_directory root | |
pid "/tmp/unicorn.app_name.pid" | |
stderr_path "#{root}/log/unicorn.log" | |
stdout_path "#{root}/log/unicorn.log" | |
listen "/tmp/unicorn.app_name.sock" | |
worker_processes 4 | |
timeout 20 | |
preload_app true | |
before_exec do |server| | |
ENV["BUNDLE_GEMFILE"] = "#{root}/Gemfile" | |
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 | |
if defined?(ActiveRecord::Base) | |
ActiveRecord::Base.connection.disconnect! | |
end | |
if defined?(Resque) | |
Resque.redis.quit | |
end | |
# Before forking, kill the master process that belongs to the .oldbin PID. | |
# This enables 0 downtime deploys. | |
old_pid = "/tmp/unicorn.app_name.pid.oldbin" | |
if File.exists?(old_pid) && server.pid != old_pid | |
begin | |
Process.kill("QUIT", File.read(old_pid).to_i) | |
rescue Errno::ENOENT, Errno::ESRCH | |
# someone else did our job for us | |
end | |
end | |
sleep 1 | |
end | |
after_fork do |server, worker| | |
if defined?(ActiveRecord::Base) | |
ActiveRecord::Base.establish_connection | |
end | |
if defined?(Resque) | |
Resque.redis = 'localhost:6379' | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
### BEGIN INIT INFO | |
# Provides: unicorn | |
# Required-Start: $remote_fs $syslog | |
# Required-Stop: $remote_fs $syslog | |
# Default-Start: 2 3 4 5 | |
# Default-Stop: 0 1 6 | |
# Short-Description: Manage unicorn server | |
# Description: Start, stop, restart unicorn server for a specific application. | |
### END INIT INFO | |
set -e | |
# Feel free to change any of the following variables for your app: | |
TIMEOUT=${TIMEOUT-60} | |
APP_ROOT=/home/deployer/apps/app_name/current | |
PID=/tmp/unicorn.app_name.pid | |
CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production" | |
AS_USER=deployer | |
set -u | |
OLD_PIN="$PID.oldbin" | |
sig () { | |
test -s "$PID" && kill -$1 `cat $PID` | |
} | |
oldsig () { | |
test -s $OLD_PIN && kill -$1 `cat $OLD_PIN` | |
} | |
run () { | |
if [ "$(id -un)" = "$AS_USER" ]; then | |
eval $1 | |
else | |
su -c "$1" - $AS_USER | |
fi | |
} | |
case "$1" in | |
start) | |
sig 0 && echo >&2 "Already running" && exit 0 | |
run "$CMD" | |
;; | |
stop) | |
sig QUIT && exit 0 | |
echo >&2 "Not running" | |
;; | |
force-stop) | |
sig TERM && exit 0 | |
echo >&2 "Not running" | |
;; | |
restart|reload) | |
sig HUP && echo reloaded OK && exit 0 | |
echo >&2 "Couldn't reload, starting '$CMD' instead" | |
run "$CMD" | |
;; | |
upgrade) | |
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT | |
then | |
n=$TIMEOUT | |
while test -s $OLD_PIN && test $n -ge 0 | |
do | |
printf '.' && sleep 1 && n=$(( $n - 1 )) | |
done | |
echo | |
if test $n -lt 0 && test -s $OLD_PIN | |
then | |
echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds" | |
exit 1 | |
fi | |
exit 0 | |
fi | |
echo >&2 "Couldn't upgrade, starting '$CMD' instead" | |
run "$CMD" | |
;; | |
reopen-logs) | |
sig USR1 | |
;; | |
*) | |
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>" | |
exit 1 | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment