Hi guys,
This thread was written by me to be used as a future reference of mine and I would like to share here for some people who is struggling with setting up Rails applications on their own Linode cloud VPS.

First of all, let me introduce what is Linode and why I choose it over its alternatives.
Linode is a cloud VPS provider which is quite well known by people who is working on cloud technology.
Linode offer various cheap plans when compared to competitors and its performance is still better from them. (based on the benchmark I found from here)
With just $19.95/mo, I got 20GB disk space, 200GB outgoing bandwidth (now incoming bandwidth is free) and 512MB of memory.
This entry level offer is unbeatable while compared to Slicehost (now bought and managed by Rackspace), Amazon EC2 or Prgmr.
Let’s me say that before I decide to go with Linode, I’ve research a lot about Rails application hosting which finally ends up with Heroku because my project has a short time of development and deployment so I can’t waste my time setting up a box for it.
When the app is live and running smoothly, now I want to improve my ROI and want to make it more cost effective when I demand for more resources.
That’s the reason why I’m moving out from Heroku and ends up with Linode.
That’s a short introduction why I ends up with Linode and now let’s get started seeing how do I set up a Rails application on Linode cloud VPS successfully.
How to set-up Rails application on Linode.
1st, Sign-up for Linode
Just pick a plan you think it is fit for your needs. For me, the Linode 512 is more than enough by now.
After picked up a plan, you will be asked to enter credit card and choose the data center location, just pick one that close to your target visitors. I saw last time there is Asia data center, anyway, I choose Newark, NJ, USA as my target will be in USA.
2nd, Create your Linux node
After sign-up was completely, now I’m going to create a new node by choosing a linux distribution to be use with. I choose Ubuntu 10.0.4 LTS which is 32-bit because there are many sources saying that 32-bit performance is better than 64-bit of Ubuntu.
Just allocate the disk space and swap size that you think it will fits your needs. For me, I just choose the maximum because I need to setup only single node. If you want to separate database server from your web server, just remain some space for your second node.
After the node was built, just push the “Boot” button to start your node now.
3rd, connect to your node using SSH
Now click on the “Remote Access” tab from your dashboard to see the IP address of your node.
Let’s see the “SSH Access” field, it should have some text like “ssh root@11.22.33.44″.
This is the command being used to connect to your node remotely.
Let’s say you are using Mac OSX or Linux, you can use terminal to execute the command.
Then, enter your specified password and you will ends up connected to your node completely.
Note that, you can remote access into your Linode without entering password by appending your computer’s public key to Linode’s authorized keys. This can be done by…
- Open up your terminal
- If you don’t have an existing public key (the file ‘id_rsa.pub’ in ‘~/.ssh/’ folder), then you should do it by issuing this command
</div>
<div>ssh-keygen -t rsa -C "youremail@email.com"</div>
<div># Note that you will be asked to enter the passphrase. Just enter and remember it.</div>
<div>
- Run this command to copy the content of your public key to the clipboard ‘cat ~/.ssh/id_rsa.pub | pbcopy’
- Now connect to your Linode through ssh
- Create a file ‘~/.ssh/authorized_keys’ and paste the content of your public key there, then save
Now try to logout from ssh and login again and you don’t need to enter the password any more.
4th, basic configuration
Begin with updating system, run these commands.
apt-get update
apt-get upgrade --show-upgraded
Next is to set the host name. This is not actually a host name or domain name you want your Linode to host. It can be anything. Let’s say I’ve named it ‘mickey’.
Run the following commands. (don’t forget to change ‘mickey’ to your own host name)
echo "mickey" > /etc/hostname
hostname -F /etc/hostname
Now it’s time to update your /etc/hosts file to let them know your host name.
I issue the command ‘vi /etc/hosts’ to edit the file.
Add the following lines into the file. (you have to enter your Linode’s IP address in the first line, and the IPv6 in the second line, also don’t forget to change ‘mickey’ and host name with your desired name)
12.34.56.78 mickey.example.com mickey
1234:1234::1234:1234:1234:1234 mickey.example.com mickey
Next, it’s time to configure the time zone. I usually set UTC as my time zone for all of my Linodes.
dpkg-reconfigure tzdata
Select UTC from the list, or just select your desired time zone.
Then you need to make a symbolic link to your time zone info.
ln -sf /usr/share/zoneinfo/UTC /etc/localtime
If you are using any other time zone than UTC, then you should find your time zone info in the ‘/usr/share/zoneinfo/’ directory.
Ok, let’s go to the next step. I hate ASCII, so I configure my box to use UTF-8 by editing the ‘~/.bashrc’ file to include these lines.
export LANG="en_US.UTF-8"
export LC_CTYPE="en_US.UTF-8"
The basic configuration is completed now.
5th, installing Ruby
First, you need to install some pre-requisite libraries.
apt-get install build-essential bison openssl libreadline6 libreadline6-dev libcurl4-openssl-dev git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev curl
Note that the above is a single line command.
If you are using MySQL, you need to execute the following command.
apt-get install mysql-server mysql-client
Also, if you are using Image Magick library, run this command.
apt-get install libmagickwand-dev imagemagick
Now it’s time to install Ruby. I choose to use RVM as it can handle multiple versions of Ruby installation. Run this shell command.
bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
Check if the RVM was installed correctly.
type rvm | head -1
It should output ‘rvm is a function’. This prove you are correct in this step.
Now I decide to install the latest version of Ruby.
rvm install ruby
If you want to install the specific version of Ruby, you can do it by…
rvm install ruby-1.9.2
Wait a few minutes and it’s time to configure the default version of Ruby to be used by the Linode.
rvm --default use 1.9.2-p290
rvm gem set use global # install gems to this gemset
gem install rdoc
gem install bundler
Now it’s time to install Passenger and Nginx and make it start up at boot.
gem install passenger
rvmsudo passenger-install-nginx-module
rvm wrapper 1.9.2-p290@global passenger
curl -L http://bit.ly/nginx-ubuntu-init-file > /etc/init.d/nginx
chmod +x /etc/init.d/nginx
update-rc.d nginx defaults
/etc/init.d/nginx start
Wooo Hooo, now my Linode is ready to run Rails app and serve web visitors.
However, for my Linode, I need Postgresql as my production database server. So, I would required to run…
apt-get install postgresql postgresql-contrib
apt-get install libpq-dev
gem install pg
Now the box we created is fully packed with Ruby, Nginx, Passenger, it’s ready now.
6th, time to deploy your Rails application
We will deploy using another user than root regards to security reason. Let’s add one by…
adduser deploy
adduser deploy rvm
Then, logout from current ssh session and re-login using the deploy user.
As I’m using GitHub as my Git server, I need to create a public key for deploy user and add the key to GitHub account.
So, I create a public key by…
ssh-keygen -t rsa -C "youremail@email.com"
Then login to GitHub account and add the key (~/.ssh/id_rsa.pub) to the GitHub account.
Also, I copy the token of my GitHub account.
Then I configure my Git.
git config --global user.name 'FirstName LastName'
git config --global user.email 'myemail@email.com'
git config --global github.user 'githubusername'
git config --global github.token 012345678901234567890 #change the long digit to your GitHub's token
Now get back to your workstation which you are using to develop your Rails application. (The following steps not being run at your Linode box!)
This step is not sure if it required or not, so please try at your own risk.
Create a file ‘setup_load_paths.rb’ in the ‘config’ directory of your Rails application. Then add the following content.
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm')
begin
rvm_path = File.dirname(File.dirname(ENV['MY_RUBY_HOME']))
rvm_lib_path = File.join(rvm_path, 'lib')
$LOAD_PATH.unshift rvm_lib_path
require 'rvm'
RVM.use_from_path! File.dirname(File.dirname(__FILE__))
rescue LoadError
# RVM is unavailable at this point.
raise "RVM ruby lib is currently unavailable."
end
end
ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
require 'bundler/setup'
Then add ‘capistrano’ into your Gemfile and run ‘bundle install’.
Now it’s time to prepare capistrano.
capify .
Then prepend the following lines in the file ‘Capfile’ which was created by the above ‘capify’ command.
# Add RVM's lib directory to the load path.
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
# Load RVM's capistrano plugin.
require "rvm/capistrano"
# Set it to the ruby + gemset of your app, e.g:
set :rvm_ruby_string, 'ruby-1.9.2-p290@global'
load 'deploy' if respond_to?(:namespace) # cap2 differentiator
# Uncomment if you are using Rails' asset pipeline
# load 'deploy/assets'
Dir['vendor/gems/*/recipes/*.rb','vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
load 'config/deploy' # remove this line to skip loading any of the default tasks
Then edit the file ‘deploy.rb’ in the ‘config’ directory with this content.
set :user, 'deploy'
set :domain, 'myrailsapp.com'
set :application, "myrailsapp"
set :repository, "git@github.com:username/repo.git" # Your clone URL
set :scm, "git"
set :branch, "master"
set :scm_verbose, true
set :deploy_via, :remote_cache
set :scm_passphrase, "password" # The deploy user's password
set :deploy_to, "/home/#{user}/#{domain}"
set :use_sudo, false
require "bundler/capistrano"
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
role :web, domain # Your HTTP server, Apache/etc
role :app, domain # This may be the same as your `Web` server
role :db, domain, :primary => true # This is where Rails migrations will run
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
after "deploy:migrations", "deploy:cleanup"
Note that you have to edit each parameters to fit your environment.
Then, you need to configure your Nginx to serve the specified domain name and map to the path to be deployed by capistrano.
Edit the file ‘/opt/nginx/conf/nginx.conf’ and add the following lines.
server {
listen 80;
server_name *.myrailsapp.com;
root /home/deploy/myrailsapp.com/current/public/;
passenger_enabled on;
}
Now it’s time to deploy your Rails application.
capistrano required you to setup for the first time, so you have to run this command for the first time only.
cap deploy:setup
Then, it is a time to deploy actual files.
cap deploy
If you are following the above instructions carefully. You should have a production of your Rails application running now.
Cheers!