There is so much confusion around deploying applications using RVM, I went down and verified. The process was quite straight forward, but I found few points that could be improved.
So all my experiments were done using fresh rails app with one model, you can find sources here: https://github.com/mpapis/ad
My goal was to be able to install rails app on server without complicated recipes and doing much on server.
So the boring part first, setup server:
- I’m assuming your domain (DNS) is configured and points to the server
- I’m assuming you have nginx up and running, most distributions have own instructions for it, but the process should be rather easy like
apt-get install nginx
- To keep good security levels we assume one user is created per application, I used this command
useradd --comment "AD - Example Rails App" -s /bin/bash -m -U ad
but you might need other command depending on the system, do not forget to generate and exchange SSH keys
- Then I had to create nginx configuration for my site
/etc/nginx/sites-available/ad.niczsoft.com`` the code bellow
- And finally link the configuration
ln -s /etc/nginx/sites-available/ad.niczsoft.com /etc/nginx/sites-enabled/ad.niczsoft.com
, do not forget to restart nginx
server {
listen 80;
server_name ad.niczsoft.com;
access_log /var/log/nginx/ad.niczsoft.com.access.log;
error_log /var/log/nginx/ad.niczsoft.com.error.log;
location / {
proxy_pass http://unix:/home/ad/app/shared/pids/unicorn.socket;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host; # this is required for HTTPS (another server section): # proxy_set_header X-Forwarded-Proto https; }
}
Server is at this point ready and trying to proxy incoming connections to our application. As mentioned above I have minimal rails application, so locally I have installed capistrano and generated basic setup with capify .
and replaced config/deploy.rb
with this https://github.com/mpapis/ad/blob/master/config/deploy.rb
We need also few gems to be added to Gemfile and then bundle install
ed:
group :development do
gem 'capistrano'
gem 'capistrano-unicorn'
gem 'capistrano-file_db'
end
but feel free to check the whole file: https://github.com/mpapis/ad/blob/master/Gemfile
On the list is one new gem I have created to simplify deployments capistrano-file_db. It’s minimalistic gem to support deployment of file based databases (defaults to sqlite3).
I have reused also existing gem capistrano-unicorn – this one was not so straight and needed minimal hacking, but I was able to get it running in few minutes, I will be fixing the problems I found shortly, hopefully my changes get merged to master soon.
Lets go through the config/deploy.rb
, the first section is pretty standard and reflects most of the configuration we did for server:
set :application, "ad"
set :deploy_to, "/home/#{application}/app"
set :user, "#{application}"
set :use_sudo, false
set :scm, :git
set :repository, "git://github.com/mpapis/ad.git"
The fun starts later, first we set ruby version to our current local selected ruby.
set :rvm_ruby_string, ENV['GEM_HOME'].gsub(/.*\//,"")
Next we tell rvm to check for remote installation in user home – as by default it checks system installation.
set :rvm_type, :user
Here we instruct rvm to install head version remotely, this line can get removed after 1.11.0 gets out, it will be defaulting back to stable.
set :rvm_install_type, :head # before rvm 1.11.0 gets released
We tell bundler to omit development dependencies, which of course are our capistrano libraries.
set :bundle_without, [:development]
And finally we instruct unicorn plugin about the proper pid path, unfortunately it was not the only place we needed to setup it, check https://github.com/mpapis/ad/blob/master/config/unicorn/production.rb for more details:
set :unicorn_pid, "#{shared_path}/pids/unicorn.pid"
That’s almost it, now lets tell capistrano where the deploy, and to always do migrations:
server "niczsoft.com", :app, :web, :db, :primary => true
before 'deploy:restart', 'deploy:migrate'
This two steps are important, they tell capistrano to install rvm and ruby on server, it will also create application gemset if used, it will use rvm_ruby_string
, so make sure to set it to something useful like `rvm current`
:
before 'deploy:setup', 'rvm:install_rvm'
before 'deploy:setup', 'rvm:install_ruby'
And on the end all the capistrano plugins we want to use:
require "rvm/capistrano"
require "bundler/capistrano"
require "capistrano-unicorn"
require "capistrano-file_db"
load 'deploy/assets'
For the deploy/assets
to work we have gem 'therubyracer'
in Gemfile.
That’s all, let deploy our application, first prepare server
cap deploy:setup
cap deploy:cold
this will take some time so grab a tee/coffee.
After server is prepared we can deploy application after every commit to repository:
cap deploy
And it’s the end of the journey, it takes a lot longer to write this tutorial then to just do the deployment, doing it second time try to fit in 10 minutes !
You can get more details on RVM / Capistrano integration in the freshly updated documentation page: http://beginrescueend.com/integration/capistrano/ also worth reading is the new project files not requiring trusting: http://beginrescueend.com/workflow/projects/#ruby-versions