Isnor Creative
Isnor Creative Blog
Ruby, Ruby on Rails, Ember, Elm, Phoenix, Elixir, React, Vue

Sep 2, 2014

Deploying Ruby on Rails To A New Digital Ocean or Linode VPS

Update April 6 2018 –– I would now recommend Nanobox for this type of deployment.

I’ve been looking recently for a better way of deploying new Rails apps to VPS – better that is than how I’ve done this on a few occasions in the past: apt-getting the whole darned thing piece by piece using Google and Stack Overflow to comb through ideas.

Past Experience With Webfaction

Previously, I used WebFaction for small business clients, but I have been finding it increasingly unreliable, and for larger clients, it feels like it may not be a solid solution.

Past Experience With Heroku

Heroku is brilliant, but I set it up for a large client recently and I’m personally finding the cost shocking. It’s been an ongoing concern of limited resources and Heroku restrictions that has forced us to scale up, which increases the cost that much more.

Past Experience With Linode

I manually set up a few Linode machines and combined with Monit, they have been kicking ass so far for years without hassle.

Talking Loudly

Searching for alternatives, I stumbled on this great talk, Deploying Rails Is Easier Than It Looks, which I missed at RailsConf 2014. I later read through Ben’s great tutorials on server setup and Capistrano deployment, and then checked out his code templates for server template and Capistrano template, and bought his book, Reliably Deploying Rails Applications.

My Notes Based On Talking Loudly

I found I had to do some tweaking and debugging to go from absolutely nothing to a deployed Rails application, but I’m hoping the hours I’ve put in will more than pay off in the long run.

These are my notes, based on Ben’s various tutorials, templates and book – from which I am able to get painlessly through the procedure of server setup and app deployment circa September 2014 on Digital Ocean.

Note: you may need to setup rbenv locally

First, I followed Ben’s steps of cloning his template and defining the deploy user credentials:

Initial Server Template Setup

git clone git@github.com:TalkingQuickly/rails-server-template.git
cd rails-server-template
bundle install
cd data_bags/users && cp deploy.json.example deploy.json 

Add deploy user password and your ssh key to deploy.json

Install cookbooks

mkdir cookbooks
bundle exec berks vendor cookbooks

Prepare server

ssh-copy-id -i /pathToYourPrivateKey root@xxx # copy up your ssh to 
bundle exec knife solo prepare root@yourip # prepare remote server for chef install
bundle exec knife solo cook root@yourip # do chef install on remote server

Create new Rails app, push it to repo

rails new myapp -D postgres # create new rails app
cd myapp # go to rails app
git init # start a git repo
git add . # add new rails app
git commit -m 'init' # initial git commit

Now could be a good time to create a Bitbucket or Github etc repo, add existing as per provider instructions

Add Capistrano template into the mix

Add Capistrano template to the rails app: https://github.com/gordonbisnor/capistrano-3-rails-template

Gems:

group :development do
  gem 'capistrano', '>= 3.3.5'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler' # for capistrano/bundler
  gem 'capistrano-rails'
end
gem 'unicorn'

Capistrano initial setup

cap production deploy:setup_config # setup remote for Capistrano deployment
ssh root@myServerIp # ssh into remote machine

On Remote Machine:

cd /home/deploy/apps/myapp/shared/config # go to app config folder
cp database.example.yml database.yml # copy to real database.yml – fill in user, pass and host: localhost
chown deploy  database.yml # if you’re logged in as root, cp file will mean that root owns file, will cause permission error
cp secrets.example.yml secrets.yml # copy secrets file, and fill in secret key base
chown deploy secrets.yml
su postgres # change session owner to postgres
psql # open postgres client

Create database on remote server:

CREATE DATABASE xxx;
CREATE USER xxx WITH PASSWORD 'xxx';
GRANT ALL ON DATABASE xxx to xxx;
\q # exit out of postgres client
exit # to get out of postgres su session

Add database credentials to database.yml, and setup secrets.yml, as well as any other config files

logout # logout of server

On Development Machine - Deploy

cap production deploy

You should now be able to visit your server’s IP address and see your site. I added a root path to routes.rb, a welcome controller and a welcome/index template to test.

For debugging I found I had to refer to /home/deploy/apps/shared/config/logs/unicorn.log a bit – I was turning up with a blank site, this happened a few times related to permissions issues and missing secrets.yml file. Hence my fork of Ben’s Github repo that addressed this. Anyway: that could come in handy for debugging purposes, along with Capistrano output, etc.

Backups

Configure pg backups for your node to backup to S3. In the Amazon control panel, specify a lifecycle rule to delete backups after 7 days for example, the rule:

db/backups/ 

Sidekiq

Gemfile gem ‘capistrano-cookbook’, require: false, group: :development gem ‘capistrano-sidekiq’, ‘>= 0.5.2’

Capfile

require 'capistrano/sidekiq'
require 'capistrano/sidekiq/monit”
require 'capistrano/cookbook/monit'

config/deploy.rb

set :sidekiq_monit_conf_dir, '/etc/monit/conf.d'

command line

bundle exec cap production sidekiq:monit:config
bundle exec cap production monit:reload
bundle exec cap production deploy

I am available for Ruby on Rails consulting work – get in touch to learn more.

Gordon B. Isnor

Gordon B. Isnor writes about Ruby on Rails, Ember.js, Elm, Elixir, Phoenix, React, Vue and the web.
If you enjoyed this article, you may be interested in the occasional newsletter.

I am now available for project work. I have availability to build greenfield sites and applications, to maintain and update/upgrade existing applications, team augmentation. I offer website/web application assessment packages that can help with SEO/security/performance/accessibility and best practices. Let’s talk

comments powered by Disqus