Setting Up Ruby on Rails On Digital Ocean
24 OCTOBER 2014Edit 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
Portto 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
figaroor 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!