So you want a way to work on multiple rails or sinatra apps on the same machine. Your different apps have different gemsets, different gem versions, and even use different versions of ruby. There are two popular tools for managing these different environments — RVM and rbenv.
Many articles have been written about which is better. Some people have very strong opinions on the topic. I think that both tools are good, and it's a matter of personal choice. I would say that rbenv is a bit lighter and simpler, whereas RVM has a bit of magic behind the scenes. Jonathan Jackson has a humorous article comparing the two.
However, you need to pick one! You absolutely cannot use both at the same time.
This is a tutorial explaining how to use rbenv on a fresh system. I am going to start with a fresh AWS image and then install everything from scratch.
As I said before, RVM and rbenv don't play nice. If you already have RVM installed, you will need to get rid of it before installing rbenv. Here are instructions on how to remove rvm.
I am going to start off by launching a fresh Ubuntu Server 13.04 (64-bit) instance on AWS. Create a new key pair called rbenv_tutorial. Create a new security group and open up ports 22 (SSH), 80 (http) and 8080 (we'll forward http traffic here). For security reasons, we're not going to allow any connections on ports below 1024. You should allow all ip addresses to connect via 8080 (so people can see your website).
Move your ssh key to the right folder:
mv rbenv_tutorial.pem ~/.ssh
Restrict the permissions on rbenv_tutorial.pem so that only your user can access — not other users on your computer. (AWS will actually enforce this; you will get an error if you do not properly restrict the permissions.)
chmod -R 700 ~/.ssh/rbenv_tutorial.pem
Now you can ssh onto your new server.
ssh -i ~/.ssh/rbenv_tutorial.pem ubuntu@ec2-54-237-59-94.compute-1.amazonaws.com
Be sure to put in your specific AWS hostname instead of mine.
You should now be on your new ubuntu server. If you have problems, check to be sure that you have allowed ssh traffic from your ip address.
Next, install git.
sudo apt-get install git
Let's make a directory to put our new apps in.
mkdir Programs
cd Programs
Next, check out rbenv into ~/.rbenv.
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
Now, add ~/.rbenv/bin to your $PATH. This will make all the rbenv command-line commands work.
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile
If you are not using Ubuntu, modify your ~/.bash_profile instead of your ~/.profile.
Next, add rbenv init to your shell to make shims and autocompletion work.
echo 'eval "$(rbenv init -)"' >> ~/.profile
If you're not using Ubuntu, then update your ~/.bash_profile instead.
Now, restart your shell as a login shell in order to make the path changes take effect.
exec $SHELL -l
You will want to install ruby-build.
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
Install some prerequisites:
sudo apt-get install gcc make libssl-dev libsqlite3-dev
Now you can install your first ruby version. I am going to install ruby-2.0.0-p247, which at the time of writing is the latest version.
rbenv install 2.0.0-p247
rbenv rehash
Let's make a new project.
mkdir my_rails4_project
cd my_rails4_project
Set a local default ruby version for this project.
rbenv local 2.0.0-p247
Check your default local ruby:
ruby -v
Install the bundler gem.
gem install bundler
Now install rails and sqlite3
gem install rails
This may take some time, so now's a good time to brew a fresh pot of coffee and browse XKCD.
Install all the gems with bundle install.
bundle install
Now generate all the rails scaffolding:
rbenv rehash
rails new ~/Programs/my_rails4_project/
We need a Javascript runtime, so let's install Node.js.
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
Now let's start the server.
rails server
You should see a message like this indicating that the server is running:
=> Booting WEBrick
=> Rails 4.0.0 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[2013-09-23 19:30:14] INFO WEBrick 1.3.1
[2013-09-23 19:30:14] INFO ruby 2.0.0 (2013-06-27) [x86_64-linux]
[2013-09-23 19:30:14] INFO WEBrick::HTTPServer#start: pid=8188 port=3000
We still can't connect to the server via http yet (in the browser). First, let's set up ip forwarding.
sudo vim /etc/sysctl.conf
In this file, uncomment this line:
net.ipv4.ip_forward=1
Now enable the changes to sysctl.conf:
sudo sysctl -p /etc/sysctl.conf
Now check that ip forwarding is enabled. This command should return a 1 (meaning forwarding is enabled):
cat /proc/sys/net/ipv4/ip_forward
Now, let's set up forwarding from 80 to 8080:
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
Next, let's open the Linux firewall to allow connections on port 80:
sudo iptables -A INPUT -p tcp -m tcp --sport 80 -j ACCEPT
sudo iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
Now, let's start up the server, this time on port 8080.
rails server -p 8080
Now, put the public ip address of your ec2 instance in your browser's addressbar. For example, my public ip is 54.237.59.94. When you do this, you should see the default rails app. It should look like this:
Now, let's create a new Sinatra project.
cd ..
mkdir my_sinatra_app
cd my_sinatra_app
I'll use ruby-1.9.3 for the Sinatra app.
rbenv install 1.9.3-p448
rbenv local 1.9.3-p448
Let's install Sinatra.
gem install sinatra
Now, let's create a new file called basics.rb.
vim basics.rb
In that file, put this code:
require 'rubygems'
require 'sinatra'
set :port, 8080
get '/' do
"Hello, World!"
end
Now start your Sinatra app:
ruby basics.rb -e production
You should see a Sinatra confirmation message like this:
== Sinatra/1.4.3 has taken the stage on 8080 for production with backup from WEBrick
[2013-09-23 20:49:56] INFO WEBrick::HTTPServer#start: pid=21862 port=8080
Now, you should be able to go to your public ip address and see your Sinatra app (which says "Hello, World") in your browser.
That's it!