Skip to content

Instantly share code, notes, and snippets.

Created May 18, 2011 14:55
  • Star 15 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Flexible Rails deployment with Capistrano and Nginx
set :domain, ENV["domain"]
set :application, domain
set :user, ENV["user"]
set :destination, ENV["destination"] || domain
set :web_conf, ENV["web_conf"] || ENV["environment"] || 'production'
raise "please set" unless domain
raise "please set user=server_username" unless user
set :port, ENV["port"] || 1234
set :repository, "."
set :scm, :git
set :deploy_via, :copy # copy code over to server, no need to configure scm on the server
set :copy_strategy, :export # only the code
set :copy_remote_dir, "/home/#{user}/apps/#{application}" # otherwise it will copy to /tmp which is bad on a shared host (dir must exist)
set :deploy_to, "/home/#{user}/apps/#{application}"
set :use_sudo, false
role :web, destination # Your HTTP server, Apache/etc
role :app, destination # This may be the same as your `Web` server
role :db, destination, :primary => true # This is where Rails migrations will run
after "deploy:update_code", "preconfigure"
desc "Configure the application with correct database and precompile assets"
task :preconfigure, :roles => :app do
# bundle gems
run "mkdir -p #{shared_path}/bundle && ln -s #{shared_path}/bundle #{release_path}/vendor/bundle"
run "cd #{latest_release}; bundle install --deployment --without development test"
# symlink database.yml: copy if not exists, then link it back (release/config/database.yml -> shared/database.yml)
run "cp -n #{release_path}/config/database.yml #{shared_path}"
run "ln -sf #{shared_path}/database.yml #{release_path}/config/database.yml"
# symlink database file and backup current one
run "ln -sf #{shared_path}/production.sqlite3 #{release_path}/db/production.sqlite3"
run "touch #{release_path}/db/production.sqlite3" # make sure at least empty file exists so it can be copied
run "cp #{release_path}/db/production.sqlite3 #{release_path}/db/production.sqlite3.backup"
# create the dir for SSL if it doesn't exist
run "mkdir -p #{shared_path}/ssl/"
# Compile SCSS
run "cd #{latest_release}; bundle exec compass compile #{release_path}"
# and also prepare nginx.conf
config_content = from_template("config/nginx.#{web_conf}.conf.erb")
put config_content, "#{release_path}/nginx.conf"
def get_binding
binding # So that everything can be used in templates generated for the servers
def from_template(file)
require 'erb'
template =, "..", file))
result =
namespace :deploy do
task :start, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
task :stop, :roles => :app do
# Do nothing.
desc "Restart Application"
task :restart, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
after "deploy", "deploy:cleanup" # leave only 5 releases
server {
listen 80;
listen 443;
ssl on;
server_name <%= domain %>;
ssl_certificate <%= "#{shared_path}/ssl/ssl.crt" %>;
ssl_certificate_key <%= "#{shared_path}/ssl/ssl.key" %>;
root <%= "#{current_path}/public" %>;
passenger_enabled on;
index index.html;
# maintenance page with proper 503 status
if (-f $document_root/system/maintenance.html) {
return 503;
error_page 503 @maintenance;
location @maintenance {
rewrite ^(.*)$ /system/maintenance.html break;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment