I originally tried to use the ~> 3.0 version of Capistrano, but fell back to the 2.15.5 version. There were a lot of changes in the new version that I did not feel like learning right at the moment...
First we will create a new user for deployment:
$ ssh into your server
$ sudo adduser deploy
Accept the defaults.
Add new user to staff and sudo groups:
$ sudo usermod -a -G staff deploy
$ sudo usermod -a -G sudo deploy
Switch user:
$ su deploy
$ cd ~
Update and Install Ubuntu dependencies:
$ sudo apt-get -y update
$ sudo apt-get -y install build-essential zlib1g-dev libssl-dev libreadline-dev libyaml-dev libcurl4-openssl-dev curl git-core python-software-properties libxslt1-dev libxml2-dev libmysqlclient-dev libsqlite3-dev nodejs imagemagick graphicsmagick-libmagick-dev-compat git-core mysql-server nginx
To make life easier, lets go ahead and add our ssh keys to the new server so that we do not have to sign in every time.
Add ssh keys:
$ mkdir ~/.ssh (on the server)
$ cat ~/.ssh/id_rsa.pub | ssh deploy@IPaddress "cat >> ~/.ssh/authorized_keys" (from your machine)
Set the Rails environment:
$ echo "export RAILS_ENV=production" >> ~/.bashrc
$ source ~/.bashrc
Now let's install Ruby, and we use a specific version for the may_app_name app. We need the url to get the source and a directory to build in:
$ wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p484.tar.gz
$ tar -zxvf ruby-1.9.3-p484.tar.gz
$ cd ruby-1.9.3-p484
$ echo "gem: --no-ri --no-rdoc" >> ~/.gemrc
$ ./configure --prefix=/usr/local
$ make
$ sudo make install
$ sudo gem install bundler
The Nginx configuration is the trickiest part of the set up. This file needs to go in the config file that was created with the Nginx install:
$ cd /etc/nginx
$ sudo vim nginx.conf (delete the contents and paste in the code from the Nginx.conf file. (Attachment A)
You will need to edit the IP address on line 22:
server @IPaddress:8080
The Unicorn configuration consists of the unicorn.rb file in the config directory.
On the server we need to create a directory for the project:
$ sudo mkdir /var/www
$ sudo chown deploy:deploy /var/www
We are going to use Capistrano for deployment. Capistrano is able to deploy to different environments such a Production, Staging, and Development. Make sure that you have the following in your Gemfile:
gem 'capistrano', '2.15.5'
and under group :development
gem 'capistrano-unicorn', :require => false
Make sure you bundle install after adding these gems.
To install Capistrano:
$ capify .
This creates a config/deploy.rb file
The main Capistrano settings are in the config/deploy.rb file. Additionally there is also a config/deploy/ directory and within that directory there may should be files for the different environments e.g. production.rb, staging.rb, etc.
It should be noted that there are different environments for Capistrano but these as not the same as the Rails environments that are available on a server. We currently have both beta and live servers running in 'Production' Rails environment. Think of the Capistrano envirement as simply the remote name for deployment purposes.
Capistrano will use the file in config/deploy that matches the cap deploy. For example "cap development deploy", will use the config/deploy/development.rb file.
The way that Capistrano works is that the main settings are in the config/deply.rb file:
my_app_name deploy.rb file:
set :default_stage, 'development'
set :stages, %w(production staging development)
require 'capistrano/ext/multistage'
require 'bundler/capistrano'
set :application, "may_app_name"
set :repository, "git@github.com:my_github/my_app_name.git"
set :deploy_to, '/var/www/may_app_name'
set :scm, :git
set :branch, 'master'
set :user, 'deploy'
set :deploy_via, :copy
set :keep_releases, 5
set :use_sudo, false
set :ssh_options, {:forward_agent => true}
after "deploy:restart", "deploy:cleanup"
namespace :deploy do
desc "symlink shared files"
task :symlink_shared, :roles => :app do
run "ln -nfs #{shared_path}/system/mongoid.yml #{release_path}/config/mongoid.yml"
run "ln -nfs #{shared_path}/system/application.yml #{release_path}/config/application.yml"
end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
before "deploy:assets:precompile", "deploy:symlink_shared"
# Unicorn
require 'capistrano-unicorn'
after 'deploy:restart', 'unicorn:reload' # app IS NOT preloaded
after 'deploy:restart', 'unicorn:restart' # app preloaded
The default_stage is the environment that will be run if not other options are passed to the 'cap deploy' call. The stages list the 3 possible stages that we can use. These will then coincide with the files in the config/deploy/ directory.
You will have to create each of these files to update with the new IP address or DNS name. Here is an example of staging.rb:
server "staging.example.com", :app, :web, :db, primary: true
set :rails_env, 'staging'
First we need to setup the Capistrano:
$ cap staging deploy:setup (or whatever server you are deploying to)
Next we will copy over a couple of configuration files to the shared directory on the server:
$ scp config/mongoid.yml deploy@IPAddress://var/www/may_app_name/shared/system
$ scp config/application.yml deploy@IPAddress://var/www/may_app_name/shared/system
If there were no errors, you can now deploy using:
$ cap staging deploy:cold (or whatever server you are deploying to)
For more documentation on Capistrano see: http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html
After all changes are pushed to the master repository and merged, deployment is as follows:
$ cap staging deploy
$ cap production deploy
worker_processes 1;
user deploy; # for systems with a "nogroup"
pid /tmp/nginx.pid;
error_log /var/www/may_app_name/shared/log/nginx.error.log;
events {
worker_connections 1024; # increase if you have lots of clients
accept_mutex off; # "on" if nginx worker_processes > 1
}
http {
include mime.types;
default_type application/octet-stream;
access_log /var/www/may_app_name/shared/log/nginx.access.log combined;
sendfile on;
tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
tcp_nodelay off; # on may be better for some Comet/long-poll stuff
<!-- types_hash_max_size 2048; -->
upstream app_server {
server IPAdress:8080;
}
server {
client_max_body_size 4G;
server_name *.example.com;
keepalive_timeout 600s;
root /var/www/may_app_name/current/public;
try_files $uri/index.html $uri.html $uri @app;
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /var/www/may_app_name/current/public;
}
}
}