Skip to content

Instantly share code, notes, and snippets.

@nowk
Created April 18, 2012 18:12
Show Gist options
  • Save nowk/2415525 to your computer and use it in GitHub Desktop.
Save nowk/2415525 to your computer and use it in GitHub Desktop.
Foreman Upstarting some Rubies
# server user ~/.rvmrc
export rvm_path="/path/to/users/.rvm"
export rvm_trust_rvmrcs_flag=1
# rubies + bundler
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
set :rvm_ruby_string, "<ruby>@<gemset>" # should be same rvm as that in the Procfile
set :rvm_type, :user
# before 'deploy:setup', 'rvm:install_ruby'
after "deploy:finalize_update", "bundle:install"
after 'deploy', 'deploy:cleanup'
require 'rvm/capistrano'
# require "bundler/capistrano" # bundler (However, this does not work well with gemsets)
load "deploy/assets" # asset pipeline
namespace :bundle do
task :install, :except => {:no_release => true} do
run [
#"source #{rvm_path} && cd #{release_path} &&",
"cd #{release_path} &&",
"bundle install",
# "--gemfile #{release_path}/Gemfile",
# "--path #{shared_path}/bundle",
# "--deployment --quiet",
"--without development test"
].join(" ")
end
end
# multi-stage
set :stages, %w(production staging)
set :default_stage, "staging"
require 'capistrano/ext/multistage'
# base
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
set :use_sudo, false
set :application, "<app name>"
set :repository, "<git repo>"
set :keep_releases, 5
# database.yml
require File.join(File.dirname(__FILE__), "deploy_database_yml.rb")
set :database_adpater, 'mysql'
# nginx sites
require File.join(File.dirname(__FILE__), "deploy_nginx_site.rb")
# foreman + upstart
require File.join(File.dirname(__FILE__), "deploy_foreman_upstart.rb")
# whenever
# set :whenever_command, "bundle exec whenever"
# require "whenever/capistrano"
# dj
# require "delayed/recipes"
# set :rails_env, "production"
# based off of https://gist.github.com/2769 Thank you!
#
Capistrano::Configuration.instance.load do
namespace :deploy do
namespace :db do
desc <<-DESC
Creates the database.yml configuration file in shared path.
By default, this task uses a template unless a template \
called database.yml.erb is found either is :template_dir \
or /config/deploy folders. The default template matches \
the template for config/database.yml file shipped with Rails.
When this recipe is loaded, db:setup is automatically configured \
to be invoked after deploy:setup. You can skip this task setting \
the variable :skip_db_setup to true. This is especially useful \
if you are using this recipe in combination with \
capistrano-ext/multistaging to avoid multiple db:setup calls \
when running deploy:setup for all stages one by one.
DESC
task :setup, :except => { :no_release => true } do
set :database_password do
Capistrano::CLI.password_prompt "Enter the database password: "
end
set :database_adapter, 'postgresql' unless exists?(:database_adapter)
# TODO http://stackoverflow.com/questions/4980877/rails-error-couldnt-parse-yaml
# seems to be a lingering issue
default_template = <<-EOF
base: &base
host: localhost
adapter: #{database_adpater}
timeout: 5000
username: #{database_username}
password: #{database_password}
# pool: 5
development:
database: #{application}_development
<<: *base
staging:
database: #{application}_staging
<<: *base
test:
database: #{application}_test
<<: *base
production:
database: #{application}_production
<<: *base
EOF
location = fetch(:template_dir, "config/deploy") + "#{rails_env}/database.yml.erb"
template = File.file?(location) ? File.read(location) : default_template
config = ERB.new(template)
run "mkdir -p #{shared_path}/db"
run "mkdir -p #{shared_path}/config"
put config.result(binding), "#{shared_path}/config/database.yml"
end
desc <<-DESC
[internal] Updates the symlink for database.yml file to the just deployed release.
DESC
task :symlink, :except => { :no_release => true } do
run "mkdir -p #{shared_path}/config"
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
end
after "deploy:setup", "deploy:db:setup" unless fetch(:skip_db_setup, false)
after "deploy:finalize_update", "deploy:db:symlink"
end
end
Capistrano::Configuration.instance.load do
namespace :deploy do
namespace :foreman do
namespace :upstart do
desc <<-DESC
DESC
task :export, :except => {:no_release => true} do
raise "No application" if application.nil?
set :foreman_a, application unless exists?(:foreman_a)
set :foreman_u, user unless exists?(:foreman_u)
set :foreman_c, "web=1" unless exists?(:foreman_c)
set :foreman_p, upstream_port if exists?(:upstream_port) # from deploy_nginx_site
set :foreman_p, 3000 unless exists?(:foreman_p)
begin
sudo "stop #{foreman_a}"
rescue
# /
end
sudo "rm -f /etc/init/#{foreman_a}"
# use `rvmsudo` vs `sudo`, only thing that worked really
run "cd #{release_path} && rvmsudo bundle exec foreman export upstart /etc/init -a #{foreman_a} -f #{release_path}/Procfile.#{stage} -u #{foreman_u} -c #{foreman_c} -p #{foreman_p}"
sudo "sed -i '1 i start on runlevel [2345]' /etc/init/#{foreman_a}.conf"
end
task :start, :except => {:no_release => true} do
sudo "start #{foreman_a}"
end
task :stop, :except => {:no_release => true} do
sudo "stop #{foreman_a}"
end
task :restart, :except => {:no_release => true} do
sudo "restart #{foreman_a}"
# run "#{sudo} start #{foreman_a} || #{sudo} restart #{foreman_a}"
end
end
end
after "deploy:update", "deploy:foreman:upstart:export"
after "deploy:update", "deploy:foreman:upstart:start"
end
end
Capistrano::Configuration.instance.load do
namespace :deploy do
namespace :nginx do
desc <<-DESC
Setup nginx virtual host configurations
DESC
task :setup, :except => { :no_release => true } do
set :server_port, 80 unless exists?(:server_port)
set :upstream_port, 3000 unless exists?(:upstream_port)
set :upstream_count, 1 unless exists?(:upstream_count)
set :upstreams do
(0...upstream_count).map do |n|
"server 127.0.0.1:#{upstream_port+n};"
end.join("\n")
end
default_template = <<-EOF
upstream domain_#{application} {
#{upstreams}
# server 127.0.0.1:3000;
# server 127.0.0.1:3001;
# server 127.0.0.1:3002;
}
server {
listen #{server_port};
server_name #{server_name};
access_log #{shared_path}/log/nginx/access.log;
error_log #{shared_path}/log/nginx/error.log;
root #{current_path}/public;
index index.html;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
if (-f $request_filename.html) {
rewrite (.*) $1.html break;
}
if (!-f $request_filename) {
proxy_pass http://domain_#{application};
break;
}
}
}
EOF
location = fetch(:template_dir, "config/deploy") + "#{rails_env}/nginx-site.erb"
template = File.file?(location) ? File.read(location) : default_template
config = ERB.new(template)
run "mkdir -p #{shared_path}/db"
run "mkdir -p #{shared_path}/config"
put config.result(binding), "#{shared_path}/config/nginx-site"
end
desc <<-DESC
Symlink the deployed nginx site configuration to sites-enabled
DESC
task :symlink, :except => { :no_release => true } do
run "mkdir -p #{shared_path}/log/nginx"
run "mkdir -p #{shared_path}/config"
run "ln -nfs #{shared_path}/config/nginx-site /opt/nginx/sites-enabled/#{server_name}"
end
end
after "deploy:setup", "deploy:nginx:setup" unless fetch(:skip_nginx_setup, false)
after "deploy:finalize_update", "deploy:nginx:symlink"
end
end
server "<ip or domain>", :app, :web, :db, :primary => true
set :user, "<user>"
set :runner, :user
set :scm, :git
set :deploy_via, :remote_cache
set :deploy_to, "/home/#{user}/webapps/#{application}"
set :branch, "<branch>"
# database.yml
set :database_username, "<username>"
# nginx sites
set :server_name, "<domain>" # web
set :upstream_port, 3000
set :rails_env, "staging"
web: subcontract --rvm "--with-rubies rvmrc" --chdir ./ -- bundle exec rails server thin -p $PORT -e <environment>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment