WinstonYW

Just Another Tech Journal

Projects

Elsewhere

Setting Up Ruby on Rails On Digital Ocean

24 OCTOBER 2014

Edit This has been updated for Ubuntu 14.10, Ruby 2.2.2 and Postgres 9.4.

Documentation of how I setup SGBusFeedback.com, a basic Ruby on Rails application backed by a PostgreSQL database on Digital Ocean.

Noting it down for my future self.

Create Droplet on Digital Ocean

  • Login to Digital Ocean and start Create-ing a Droplet
  • Size : $5/mth
  • Region : Singapore
  • Image : Linux Distribtions > Ubuntu 14.04 x64
  • Add SSH key for easy access to the Droplet
  • Create Droplet!

Set Up Droplet

Assuming that your SSH key has been set up properly, SSH into your Droplet.

machine$> ssh root@<ipaddress>

Add a Deploy User

Create a deploy user on the Droplet.

droplet$> sudo adduser deploy
droplet$> sudo adduser deploy sudo #add to sudo group

Create a SSH key on your machine, and upload the key.

machine$> ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/winston/.ssh/id_rsa): id_deploy_digital_ocean
...

Copy the SSH key to the Droplet.

On Mac? brew install ssh-copy-id. On Linux? You already have ssh-copy-id.

machine$> ssh-copy-id -i ~/.ssh/id_deploy_digital_ocean deploy@<ipaddress>

Now you can login to your Droplet with:

machine$> ssh-add ~/.ssh/id_deploy_digital_ocean
machine$> ssh deploy@<ipaddress>

Harden Droplet

Modify SSH settings /etc/ssh/sshd_config in the Droplet.

  • Add PermitRootLogin without-password (What?)
  • Add UseDNS no (What?)
  • Change Port to something unique and take note. E.g. 8888

Reload SSH with reload ssh.

Verify your SSH settings with your new user. In a new Terminal:

machine$> ssh -p 8888 deploy@<ipaddress>

Bonus. Add this to ~/.ssh/config on your machine so that login will be a breeze.

# in ~/.ssh/config
Host    <appname>
    HostName        <ipaddress>
    Port            8888
    User            deploy
    IdentityFile    ~/.ssh/id_deploy_digital_ocean
machine$> ssh <appname>

Update and Upgrade Ubuntu

A Ruby on Rails server requires quite a few things. Installed these as the deploy user.

droplet$> sudo apt-get update
droplet$> sudo apt-get upgrade
droplet$> sudo apt-get install git-core
droplet$> sudo apt-get install nodejs # for assets compilation.

RVM

Install RVM.

droplet$> curl -L https://get.rvm.io | bash -s stable
# If an error about gpg occurs, follow the instructions..
droplet$> gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
# https://github.com/wayneeseguin/rvm/issues/3110

Relogin to shell, install RVM requirements, and Ruby.

droplet$> source /etc/profile.d/rvm.sh
droplet$> echo "source /etc/profile.d/rvm.sh" >> ~/.bashrc
droplet$> rvm requirements
droplet$> rvm install 2.2.2
droplet$> rvm use 2.2.2 --default
droplet$> ruby -v

RubyGems Setup

Prevent RubyGems from installing docs.

droplet$> echo "gem: --no-ri --no-rdoc" > ~/.gemrc

Install Nginx and Passenger

Follow the instructions on the Official Documentation.

Condensed Version:

Install Phusion's PGP key and add HTTPS support for ATP.

droplet$> sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
droplet$> sudo apt-get install apt-transport-https ca-certificates

Add Passenger's repository. Just one.

droplet$> sudo sh -c 'echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main" >> /etc/apt/sources.list.d/passenger.list'
droplet$> sudo chown root: /etc/apt/sources.list.d/passenger.list
droplet$> sudo chmod 600 /etc/apt/sources.list.d/passenger.list
droplet$> sudo apt-get update

Install Nginx and Passenger packages.

# The Official Documentation uses `nginx-extras` but `nginx-full` is good enough.
droplet$> sudo apt-get install nginx-full passenger

Edit /etc/nginx/nginx.conf and uncomment passenger_root and passenger_ruby.

Also find out where your ruby is, and use that for passenger_ruby.

droplet$> passenger-config --ruby-command
  Command: /usr/local/rvm/gems/ruby-2.2.2/wrappers/ruby
  Version: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
  To use in Apache: PassengerRuby /usr/local/rvm/gems/ruby-2.2.2/wrappers/ruby
  To use in Nginx : passenger_ruby /usr/local/rvm/gems/ruby-2.2.2/wrappers/ruby
  To use with Standalone: /usr/local/rvm/gems/ruby-2.2.2/wrappers/ruby /usr/bin/passenger start
droplet$> sudo vi /etc/nginx/nginx.conf
... Edits ..
droplet$> sudo service nginx restart

Install PostgreSQL

Install it.

droplet$> sudo apt-get install postgresql-9.4 libpq-dev

Set up Postgres user.

The password that you used here will be used in your app's database.yml.

droplet$> sudo su - postgres
droplet$> psql -c"alter user postgres with password 'strong123password';"

Create the Production database.

droplet$> psql
psql> create database <production_dbname>;
psql> exit

Connect GitHub Repo to Droplet

Create a SSH key on the Droplet, and then add it to the GitHub repo.

Follow the instructions here: https://help.github.com/articles/generating-ssh-keys/

Make sure you run this droplet$> ssh -T git@github.com.

This will ensure that Mina can deploy with GitHub.

Setup Mina

Follow the instructions on Mina's README.

Condensed Version:

Init Mina on your application.

machine$> mina init
Created config/deploy.rb.

Use rvm or rbenv.

require 'mina/rvm'
# require 'mina/rbenv'

Update config/deploy.rb with Droplet's Details.

set :domain,       <ipaddress>
set :deploy_to,   '/home/deploy/<app_domain'
set :repository,  'git@github.com:<user>/<repo>.git'
set :branch,      'master'
set :user,        'deploy'
set :port,        '8888'
....
task :environment do
  queue 'source ~/.bash_profile'

  # For those using RVM, use this to load an RVM version@gemset.
  invoke :'rvm:use[ruby-2.1.4]'
end

SetUp Mina on Droplet.

machine$> mina setup
-----> Using RVM environment 'ruby-2.1.4'
       Using /home/demo/.rvm/gems/ruby-2.1.4
-----> Setting up /home/deploy/<app_domain>

       total 16
       drwxrwxr-x 4 deploy deploy 4096 Nov  5 02:00 .
       drwxr-xr-x 8 deploy deploy 4096 Nov  5 02:00 ..
       drwxrwxr-x 2 deploy deploy 4096 Nov  5 02:00 releases
       drwxrwxr-x 4 deploy deploy 4096 Nov  5 02:00 shared

-----> Done.
-----> Be sure to edit 'shared/config/database.yml'.
-----> Be sure to edit 'shared/config/secrets.yml'.
       Elapsed time: 1.00 seconds

Important! Update shared/config/database.yml and shared/config/secrets.yml on the Droplet.

#database.yml
production:
    adapter: postgresql
    encoding: unicode
    database: <production_dbname>
    username: postgres
    password: strong123password
    host: localhost
#secrets.yml
production:
    secret_key_base: <Generated from `rake secret`>

You might also need these settings in .bash_profile.

# vi .bash_profile
export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8

Now, you can deploy your application to the Droplet.

machine$> mina deploy

Update Nginx Configuration

Update the file /etc/nginx/sites-enabled/default with these settings:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    server_name         <app_domain>;
    passenger_enabled   on;
    rails_env           production;
    root                /home/deploy/<app_domain>/current/public;
}

Restart the Nginx server, you should be able to see your app at the ipaddress.

droplet$> sudo service nginx restart

Next Steps

At this point, you already have your app up and running at ipaddress.

You will probably need to do the following to make it work nicely:

  • Use figaro or add ENV variables to .bash_profile.
  • Point DNS to the ipaddress.
  • Explore other configurations for your Nginx (static 40 or 50)
  • Put in place backup strategies for your PostgreSQL (maybe use RDS instead?)

That's it!

Troubleshooting

Sometimes, the $5/mth Droplet might complain of inadequate swap space. Read this.

Also, Nginx error logs are pretty handy. Available at /var/log/nginx/error.log.

Resources

Reading these really helped!

comments powered by Disqus