Capistrano Deploy for Shared Hosting with GIT Repository
Author: Karl | Filed under: RailsWould you like to deploy your Rails apps on a shared hosting account via Capistrano? I keep a couple of small projects on A Small Orange and since I update them so infrequently, I can never remember all the steps. Duh, that’s what Capistrano was made for. So I took a night and wrote the following deployment script. There are a couple of requirements:
- Your project is in a GIT repository, local or remote.
- The GIT repository only needs to be accessible from your local machine (ASO servers do not support GIT).
- WARNING: running any part of this script will completely delete your /public_html directory!
- You only need modify the first FOUR ’set’ lines.
A shared/system_stopped directory will be created on the server, any files in here will be served when you do a ‘cap deploy:web:disable’. You can add a ’system_stopped’ directory to your project and those files will automatically be copied into the shared directory.
This script works best if you start from the beginning as this is a new deployment as a couple of directories need to be created:
deploy:setup deploy:check deploy:cold
There are a few commented out lines that you may wish to uncomment. I tried to explain their use, so you may wish to read over each function.
Lest I repeat myself… WARNING: this will completely delete your /public_html directory! Make sure you have a backup before you run any function in this script.
I plan on adding a full db backup option (run before migrations, or at will) and a production.log rotation.
set :application, "mywebapp"
set :repository, "git@myrepository.com:mywebapp.git"
set :domain, "mywebapp.com"
# user is the login name for the shared hosting account
# it should also be the name of your home directory i.e. /home/my-user-name
set :user, "myusername"
# this will place you app outside your /public_html
# and protect your app file from exposure
set :deploy_to, "/home/#{user}/#{application}"
set :scm, :git
# set :deploy_via, :remote_cache # if your server has direct access to the repository
set :deploy_via, :copy # if you server does NOT have direct access to the repository (default)
set :git_shallow_clone, 1 # only copy the most recent, not the entire repository (default:1)
ssh_options[:paranoid] = false
set :use_sudo, false
set :keep_releases, 2 # only keep a current and one previous version to save space
role :app, domain
role :web, domain
role :db, domain, :primary => true
task :update_public, :roles => [:app] do
run "chmod 755 #{release_path}/public"
run "chmod 755 #{release_path}/public/dispatch.*"
end
# remove the .git directory and .gitignore from the current release
task :remove_git_directories, :roles => [:app] do
run "rm -rfd #{release_path}/.git"
run "rm #{release_path}/.gitignore"
end
# this lets us keep the system_stopped files in project
task :copy_system_stopped_files, :roles => [:app] do
run "cp -f #{release_path}/public/system_stopped/* #{shared_path}/system_stopped/"
end
after "deploy:update_code", :update_public
after "deploy:update_code", :copy_system_stopped_files
after "deploy:update_code", :remove_git_directories
# create a symlink from the current/public to ~/public_html
task :create_public_html, :roles => [:app] do
run "ln -fs #{current_path}/public ~/public_html"
end
after "deploy:cold", :create_public_html
# create a directory in shared to hold files that will be servered
# when the system is stopped, and a config directory
task :create_shared_directories, :roles => [:app] do
run "mkdir -p #{shared_path}/system_stopped"
run "mkdir -p #{shared_path}/config"
end
after "deploy:setup", :create_shared_directories
# remove the symlink for ~/public_html
task :remove_public_html, :roles => [:app] do
run "rm ~/public_html"
end
# creates a symlink to ~/public_html to the shared/system_stopped directory
# places files you want served in this dir for when the system is stopped
task :create_public_html_to_stopped, :roles => [:app] do
run "ln -fs #{shared_path}/system_stopped ~/public_html"
end
# we need to override the default start/stop/restart functions
namespace :deploy do
desc "Restart the web server. Killing all FCGI processes."
task :restart, :roles => :app do
# for most hosts, all you need to do is stop all FCGI processing running
run "killall -q dispatch.fcgi"
# but some hosts can restart by touching the dispatch file
#run "chmod 755 #{current_path}/public/dispatch.fcgi"
#run "touch #{current_path}/public/dispatch.fcgi"
end
desc "Start the web server. Really nothing to do for shared hosting."
task :start, :roles => :app do
remove_public_html
create_public_html
deploy.restart
end
desc "Stop the web server and present maintenance page."
task :stop, :roles => :app do
remove_public_html
create_public_html_to_stopped
end
namespace :web do
desc "Make application web accessible again."
task :enable, :roles => [:app] do
deploy.start
end
desc "Present system maintenance page to users."
task :disable, :roles => [:app] do
deploy.stop
end
end
end
Tags: capistrano, GIT, Rails
May 6th, 2008 at 2:56 pm
Thanks for sharing this. Site5.com doesn’t host git either. I have not used capistrano before and I want a clean way to install this new rails app I have been working on http://real-estate.ilikeutah.com. I have a feeling that we may be working on common elements.
May 6th, 2008 at 6:14 pm
@captproton: if you have any ideas to improve the deploy script, let me know and I’ll update the post.
Due to the recent release of Capistrano 2.3 I’ll be updated the script to use some of the new features.
May 15th, 2008 at 8:43 am
Oh, are you using Github.com?
May 15th, 2008 at 9:36 am
No. I setup a git host on my office ubuntu server. GitHub is very nice, but most of my projects are not open source, and I would rather save the money.
Take a look at hosting-git-repositories-the-easy-and-secure-way if you haven’t already. It’s what I followed to setup my git ’server’ and it works like a charm.
May 28th, 2008 at 10:47 am
[...] I said in my original post Capistrano Deploy for Shared Hosting with GIT Repository, I would add the ability to rotate log files and backup your database. Also added a couple [...]