Goals of this tutorial:
- deploy a new Rails app with capistrano
- make it fast (total process takes less than 5 minutes)
- make it simple (no unecessary config)
- manual ssh to the server not required
Rails application stack:
- nginx
- unicorn
- postgresql
This tutorial presumes:
- you already bought a server or a VPS
- the server is provisioned for Rails (all required packages installed)
If you still need to provision the server, there's a easy-chef-rails project that should help you with that.
In Gemfile
:
group :development do
gem 'capistrano', '>= 3.2.1'
gem 'capistrano-rbenv', '~> 2.0' # idiomatic rbenv support
gem 'capistrano-rbenv-install' # ensures the right ruby version is installed
gem 'capistrano-bundler', '~> 1.1.2' # support for bundler
gem 'capistrano-rails', '~> 1.0' # automatic migrations and asset compilation
gem 'capistrano-unicorn-nginx', '~> 2.0' # plug-n-play nginx and unicorn
gem 'capistrano-postgresql', '~> 3.0' # plug-n-play postgresql
gem 'capistrano-safe-deploy-to', '~> 1.1' # ensures deploy path for the app exists
gem 'capistrano-ssh-doctor' # helps with debugging ssh-agent forwarding
end
and now install gems:
$ bundle install
The following command will create required capistrano files in your project:
$ bundle exec cap install
By adding the following to the Capfile
, we'll include all the gems installed in the previous step:
require 'capistrano/rbenv'
require 'capistrano/rbenv_install'
require 'capistrano/bundler'
require 'capistrano/rails'
require 'capistrano/unicorn_nginx'
require 'capistrano/postgresql'
require 'capistrano/safe_deploy_to'
require 'capistrano/ssh_doctor'
Capistrano itself requires some configuration love. In config/deploy.rb
(file created by capistrano installer):
lock '3.2.1'
# application name
set :application, 'myapp'
# deploy directory on the server. Will be ie: '/var/www/myapp_production'
set :deploy_to, -> { "/var/www/#{fetch(:application)}_#{fetch(:stage)}" }
# capistrano will download an app from "master" branch of this repository:
set :repo_url, '[email protected]:you/your_repo.git'
# change to ruby version you need
set :rbenv_ruby, '2.0.0-p353'
and lastly, capistrano has a stage-related files since version 3.0. We'll deploy to production, so edit config/deploy/production.rb
(you can delete other content from that file):
# ssh configuration options. Make sure the following works: $ ssh <deploy_user>@<server_ip>
server '<server_ip>', user: '<deploy_user>', roles: %w{web app db}
# only if your app already has a domain, then add:
# set :nginx_server_name, 'mydomain.com'
To debug you ssh-agent setup run:
$ bundle exec cap production ssh:doctor
If you get any errors in the report at the end, fix them by following the instructions. Important: order matters so start by solving the first error you get. It is very probable that "solving" one or two initial errors will actually make everything work. A lot of the checks are inter-dependent. So don't be discouraged if you see a lot of the errors in the beginning.
Once ssh:doctor
report is successful, you're ok with proceeding to the next step.
This is the easiest step. To setup the server:
$ bundle exec cap production setup
and finally, your server is ready for deployment:
$ bundle exec cap production deploy
sit back and relax!
The following has been done on the server during the setup
phase:
- if not present, required ruby (defined with
rbenv_ruby
) will be installed - the application database is created on the server
- nginx and unicorn are properly configured
And these are roughly the deploy
steps:
- app itself will be cloned from the repo
- migrations will run
- assets will precompile
... along with a bunch of smaller tasks.
When it's all done, hit <server_ip> (or enter domain) in the browser and confirm your app is live!
Now that the app is live, how do you deploy new application updates? Luckily, capistrano makes that trivial.
- make changes to the app and commit them:
$ git commit "changes"
- push changes to online repo:
$ git push origin master
- deploy:
$ bundle exec cap production deploy
Capistrano has a built in support for multiple environments.
Deploying an app to a new environment is really easy. We'll presume a new environment is staging, so edit config/deploy/staging.rb
to look like this:
server '<staging_server_ip>', user: '<deploy_user>', roles: %w{web app db}
# only if your app already has a domain, then add:
# set :nginx_server_name, 'staging.mydomain.com'
You'll notice the above is very similar to config/deploy/production.rb
.
All you have to do now is:
$ bundle exec cap staging deploy
and soon your app's staging environment will be live!
This tutorial has hopefully shown you how quick and easy rails application deployment could be.
Even though it's tempting, hopefully you'll never again do $ git push heroku master
:)
Happy deploying!