Skip to content

Instantly share code, notes, and snippets.

@benfoley
Last active September 26, 2016 23:47
Show Gist options
  • Save benfoley/06e317dba0d080290eea to your computer and use it in GitHub Desktop.
Save benfoley/06e317dba0d080290eea to your computer and use it in GitHub Desktop.
Config files for a Capistrano3 Unicorn Rbenv Ruby Nginx test app
Sample files for a basic Unicorn Capistrano3 setup - like something for DigitalOcean
Set up a user deploy, in new group deployers
require 'bundler/capistrano'
load 'deploy/assets'
set :application, 'eopas'
set :repository, 'git@bitbucket.org:twogalahs/eopas-dev.git'
set :scm, :git
role :web, 'deploy@162.243.107.145'
role :app, 'deploy@162.243.107.145'
role :db, 'deploy@162.243.107.145', :primary => true # This is where Rails migrations will run
set :deploy_to, "/home/deploy/#{application}"
set :user, 'deploy'
set :use_sudo, false
set :deploy_via, :remote_cache # :copy
set :keep_releases, 2
set :default_environment, {
'PATH' => "$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
}
set :assets_prefix, "" # gets appended to public
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system XSLT SCHEMAS}
before "deploy:assets:precompile", "deploy:symlink_shared"
before "deploy:assets:precompile", "deploy:symlink_db_config"
namespace :deploy do
desc "Symlink XML folders on each release."
task :symlink_shared do
puts " Symlinking SCHEMAS and XSLT"
run "ln -nfs #{shared_path}/SCHEMAS #{release_path}/public/SCHEMAS"
run "ln -nfs #{shared_path}/XSLT #{release_path}/public/XSLT"
end
desc "Symlinks database.yml"
task :symlink_db_config do
puts " Symlinking database config"
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
end
# Unicorn
require 'capistrano-unicorn'
after 'deploy:restart', 'unicorn:restart' # app preloaded
# Delayed job
require 'delayed/recipes'
# after "deploy:stop", "delayed_job:stop"
# after "deploy:start", "delayed_job:start"
# after "deploy:restart", "delayed_job:restart"
namespace :delayed_job do
desc "Stop the delayed_job process"
task :stop, :roles => :app do
run "cd #{current_path} && RAILS_ENV=production script/delayed_job stop"
end
desc "Start the delayed_job process"
task :start, :roles => :app do
run "cd #{current_path} && RAILS_ENV=production script/delayed_job start"
end
desc "Restart the delayed_job process"
task :restart, :roles => :app do
stop
start
end
end
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
set :stage, :production
set :branch, 'master'
set :rails_env, 'production'
role :app, %w{deploy@xxx.xxx.xxx.xxx}
role :web, %w{deploy@xxx.xxx.xxx.xxx}
role :db, %w{deploy@xxx.xxx.xxx.xxx}
# config valid only for current version of Capistrano
lock '3.4.0'
set :application, 'APP_NAME'
set :user, 'deploy'
set :repo_url, "git@bitbucket.org:BITBUCKET_USERNAME/#{fetch(:application)}.git"
set :deploy_to, "/home/#{fetch(:user)}/#{fetch(:application)}"
set :use_sudo, false
# set :deploy_via, :copy
set :deploy_via, :remote_cache
set :copy_exclude, [ '.git' ]
set :rbenv_type, :user # or :system, depends on your rbenv setup
set :rbenv_ruby, '2.3.0' # Match the Ruby versions
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w{rake gem bundle ruby rails}
set :rbenv_roles, :all # default value
set :preload_app, true
set :keep_releases, 3
set :linked_files, %w{config/database.yml}
set :linked_dirs, %w{bin log tmp}
# must match where the config is kept. Default is CURRENT_PATH/config/unicorn/RAILS_ENV.rb
set :unicorn_config_path, "config/unicorn.rb"
set :assets_roles, [:app]
# must match the pid setting in /etc/init.d/unicorn_testapp
set :unicorn_pid, "/#{fetch(:deploy_to)}/shared/pids/unicorn.pid"
namespace :deploy do
# Symlink nginx config and unicorn's init script from current/config/src/ to xx
# Make the source files executable
desc "Symlinks config files for Nginx and Unicorn."
namespace :symlink do
task :server_config do
on roles(:app) do
execute "rm -f /etc/nginx/sites-enabled/default"
execute "ln -nfs #{current_path}/config/src/nginx.conf /etc/nginx/sites-enabled/#{fetch(:application)}"
execute "ln -nfs #{current_path}/config/src/unicorn_init.sh /etc/init.d/unicorn_#{fetch(:application)}"
execute "chmod +x #{current_path}/config/src/nginx.conf"
execute "chmod +x #{current_path}/config/src/unicorn_init.sh"
end
end
end
# Restart unicorn -- https://github.com/tablexi/capistrano3-unicorn
task :restart do
invoke 'unicorn:restart'
end
end
# Don't need to do this task on every deploy, just call it for first deploy
# cap production deploy:symlink:server_config
after 'deploy:publishing', 'deploy:symlink:server_config'
after 'deploy:symlink:server_config', 'deploy:restart'
# Need to restart nginx?
# Capistrano task will symlink this file to /etc/nginx/sites-enabled/APP_NAME
upstream app {
# Path to Unicorn SOCK file, as defined previously
server unix:/home/deploy/APP_NAME/shared/sockets/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
root /home/deploy/APP_NAME/current/public;
try_files $uri/index.html $uri @app;
location ~ ^/(assets)/ {
root /home/deploy/APP_NAME/shared/;
gzip_static on;
expires max;
add_header Cache-Control public;
}
location @app {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
# long timeouts for eopas!
proxy_connect_timeout 300;
proxy_read_timeout 300;
proxy_send_timeout 300;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
#!/bin/sh
# Capistrano task will symlink this file to /etc/init.d/unicorn_testapp
### BEGIN INIT INFO
# Provides: unicorn
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the unicorn app server
# Description: starts unicorn using start-stop-daemon
### END INIT INFO
set -e
USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"
# app settings
USER="deploy"
APP_NAME="scruffy"
APP_ROOT="/home/$USER/$APP_NAME/current"
ENV="production"
# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="/home/$USER/$APP_NAME/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"
# make sure the app exists
cd $APP_ROOT || exit 1
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}
case $1 in
start)
sig 0 && echo >&2 "Already running" && exit 0
echo "Starting $APP_NAME"
su - $USER -c "$CMD"
;;
stop)
echo "Stopping $APP_NAME"
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
echo "Force stopping $APP_NAME"
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload|upgrade)
sig USR2 && echo "reloaded $APP_NAME" && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
$CMD
;;
rotate)
sig USR1 && echo rotated logs OK && exit 0
echo >&2 "Couldn't rotate logs" && exit 1
;;
*)
echo >&2 $USAGE
exit 1
;;
esac
# from http://theflyingdeveloper.com/server-setup-ubuntu-nginx-unicorn-capistrano-postgres/
#
# set path to application
app_dir = '/home/deploy/APP_NAME'
shared_dir = "#{app_dir}/shared"
working_directory "#{app_dir}/current"
# Set unicorn options
worker_processes 2
preload_app true
timeout 300 # long timeout for eopas!
# Set up socket location
listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64
# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"
# Set master PID location
pid "#{shared_dir}/pids/unicorn.pid"
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
# Before forking, kill the master process that belongs to the .oldbin PID.
# This enables 0 downtime deploys.
old_pid = "#{shared_dir}/pids/unicorn.pid.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
after_fork do |server, worker|
# the following is *required* for Rails + "preload_app true",
if defined?(ActiveRecord::Base)
ActiveRecord::Base.establish_connection
end
end
source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.5.1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.1.0'
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Use Unicorn as the app server
gem 'unicorn'
group :development, :test do
gem 'capistrano', '~> 3.1'
gem 'capistrano-bundler'
gem 'capistrano-rails'
gem 'capistrano-rbenv'
gem 'capistrano3-unicorn', :require => false
end
group :development do
# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment