Quickstart: Running Rails on your own Digital Ocean VPS

I’ve been working on a couple different web application projects using Rails 3.2, and they’re now at the point where they need to go onto a publicly accessible development/staging/production platform.

The quickest, most hassle-free solution is to use Heroku for deployment - create a Heroku web application from the command line, git push heroku master, and you’re live! There’s something to be said for using Heroku for a development environment - you can easily push copies of your server, it’s free if you only use one dyno and no SSL, and they handle all of the maintenance and operations.

Unfortunately, once you look at taking your web application up just one level towards production (two dynos, so Heroku doesn’t spin down your application, a database with more than 10K rows, and SSL), you’re looking at $65/month. Not a big deal once the project gets going, but if you’re launching a lot of web services, it will add up.

I’ve had good luck with hosting on DigitalOcean, a VPS provider that uses SSD disks for its servers. The lowest cost plan is $5/month for 512 megs of RAM and a 20-gig SSD. I really like the performance of a 512-megabyte VPS I’m currently using to host a couple of PHP/MySQL projects. I moved those sites over from another VPS provider who was acquired by a larger company, and I’ve gotten much better performance for $5/month than I was for $25/month.

Previously, it had been a pain to install RVM, nginx, and Unicorn all together on Ubuntu - I’d tried messing with Vagrant, Chef recipes, Passenger, and a bunch of other half-baked devops scripts. I find it a little strange that no one’s done a good job writing a simple Ubuntu->RVM devops setup script with sensible defaults, but that’s fine. I ended up setting up my first DigitalOcean Rails VPS with Passenger, which wasn’t too bad, but it wasn’t easily scalable.

In the meantime, DigitalOcean released an RVM/Rails image (with MySQL, but you can easily install PostgreSQL instead if you want), so you can click a button and get a fully provisioned Rails/RVM/nginx/unicorn/MySQL server in 60 seconds after signing up with DigitalOcean.

What’s missing there is a deployment story  - if you just want to hack on the server, great, but that doesn’t scale either. The easiest way to deploy Rails sites is Capistrano, which is covered in this fantastic tutorial (How to Deploy a Rails 4 App with git and Capistrano by Rob McLarty). Rather than recap everything in that tutorial, I’ll let you go through it.

Of course that tutorial doesn’t exactly match the setup that DigitalOcean uses for its Rails droplet, so I had to make a few changes to support RVM and the Capistrano way of deploying apps using current and releases directories.

I’m not a huge fan of RVM, and you’re going to run into problems because RVM basically runs as a shell script on interactive login, and not non-interactive login, which Capistrano uses.

You’lll need to modify the deploy.rb Capistrano file from the above tutorial for the default DigitalOcean setup . I also changed the shell used in the above tutorial to bash. Extremely important is to set the bundle command used, or you’ll get lots of errors about the bundler gem not being installed. Here’s the first part of my deploy.rb file with my changes.

require 'bundler/capistrano'
$:.unshift(File.expand_path("./lib", ENV["rvm_path"]))

require 'rvm/capistrano'

default_run_options[:shell] = 'bash'
set :rvm_ruby_string, "ruby-1.9.3-p429"
set :rvm_type, :user
set :bundle_cmd, 'source $HOME/.bash_profile && bundle'

I also included the RVM Capistrano plugin, and specified the RVM ruby string to use, though that could probably be taken out for most projects.

The other place you’ll run into problems using Capistrano and DigitalOcean’s Rails provider is in setting up the nginx and unicorn directories.

Modify the /etc/nginx/sites-enabled/default file to change the location of your Rails app from /home/rails to /home/rails/current

Modify two unicorn files:

In /home/unicorn/unicorn.conf, change the working directory to /home/rails/current

In /etc/default/unicorn, change the APP_ROOT to /home/rails/current

Run capistrano to deploy the rails app: cap deploy

From the server, restart unicorn and nginx, and your server should be pointing to your new rails app!

service unicorn restart
service nginx restart

Let me know if this how to helps you sort out deploying Rails apps to DigitalOcean! If you have questions or feedback, or if something else needs to be included, either leave a comment here or contact me directly.