How To Set Up a Ruby Dev Environment on Ubuntu Linux27 Sep 2020
Setting up a development environment correctly might not seem like a big deal at first, but an incorrectly set-up environment can cause a lot of problems down the road if you’re not careful. In my experience, the internet’s full of solutions – both good and bad – for environment problems, but often does a poor job of explaining why a solution’s good or bad. And installing Ruby can be tricky if you’ve never done it before. So here’s my advice.
Let’s say you want to run a gem – for example, Jekyll. To run the gem, you’ll have to install Ruby and then install the gem. Rather than jumping straight to the best solution, I’m first going to look at what not to do so you can understand what problems this might cause. After seeing what not do to, we’ll look at a couple better solutions, and we’ll see the advantages and disadvantages of each. By the end, I’ll show you what I think is the best way to install Ruby so you can avoid environment headaches.
What Not To Do
When you’re a beginner with Ruby or Linux (we’ve all been there) and all you
want to do is run a gem,
sudo appears to solve all your problems. You might
come across advice like this:
$ sudo apt-get update && sudo apt-get install ruby
Install the gem
$ sudo gem install jekyll
Use the gem. Done.
$ jekyll --version jekyll 4.1.1
While this might appear to solve everything, it can also create a host of new
problems. For example, maybe you’ll need to install some gems with
Bundler a few days later. If you try using
install gems with Bundler, you’ll probably see a warning like this one:
$ sudo bundle install Don't run Bundler as root. Bundler can ask for sudo if it is needed, and installing your bundle as root will break this application for all non-root users on this machine.
Bundler warns you that this isn’t the best way to do things - root will be the
owner of all the files bundler installs, and from that point on you’ll have to
sudo to get gem updates until you fix your file permissions.
But beyond this, installing gems with
sudo can actually be dangerous -
particularly since gems can execute scripts when they install. For example, see
killergem. Even if you didn’t install
this malicious gem directly, if one of the gems you try to install even depends
on a malicious or compromised gem, it could be bad news. Let’s look at a better
A Quick & Simple Solution
So if the above steps are problematic, what can we do that’s safer? Maybe you just want to run a quick script or gem and you don’t care about managing specific versions of Ruby. You want a simple solution that works and doesn’t have permissions problems.
Install Ruby. For simplicity, we’ll use whatever version is in Ubuntu’s repositories. Using sudo is OK here because we’re using apt-get.
$ sudo apt-get install ruby
Install the gem. Since we’re installing a gem (rather than a system package from apt), we won’t use sudo. Instead, we’ll pass the
--user-installflag when we install our gem.
$ gem install --user-install jekyll
--user-installportion is key – it installs the gem in a directory our user has permissions to. You’ll probably see a warning like this:
WARNING: You don’t have /home/mike/.gem/ruby/2.7.1/bin in your PATH, gem executables will not run.
That’s OK – we’ll fix it in the next step.
As the warning says,
~/.gem/ruby/2.7.1/binisn’t in our PATH. So let’s put it there. Ubuntu comes with a
~/.profilefile that adds a couple things to our path by default, and I like to build on that file. Modify it to include these lines:
# Add User Ruby Gems if [ -d "$HOME/.gem/ruby/2.7.1/bin" ]; then PATH="$HOME/.gem/ruby/2.7.1/bin:$PATH" fi
For the changes to take effect, we can either log out and log back in or simply run
source ~/.profile. We can confirm it worked by running
which jekyll, which should return
Done. We’ve installed the
jekyll gem without using
sudo. In this case, for
simplicity, we’re relying on our OS to provide an easy-to-user Ruby installer.
This is fine, but it does mean we’re stuck with the version of Ruby that our
OS provides. Which is fine for simple needs (like running a few simple scripts
or gems), but might not be ideal if, for example, you’re developing a Ruby
application that requires a specific version and want to upgrade your version of
Ruby independently of your OS. If you’re regularly programming in Ruby, it will
be important for you to install the version of Ruby required by your
application, and possibly install multiple versions of Ruby for multiple
applications or during upgrades.
The Best Solution: How to Install Ruby with rbenv
The best solution for installing Ruby and managing your installation is a Ruby version manager. Using a version manager allows you to have multiple versions of Ruby installed at once and select the one you want to use. It also decouples your Ruby installation from your OS package manager, and provides a solution for doing everything without sudo. There are a few options for version managers. RVM is reputable and has a good following, but in my humble opinion rbenv is simpler and easier to use. To install rbenv, you can find the most up-to-date official instructions here, but they can be a little confusing, and they’ll boil down to something like this:
Remove old Ruby versions first!
It is confusing to have Ruby installed by both apt-get and rbenv on the same system. If you've already installed Ruby with apt-get, you should remove it before continuing. You can do so with
sudo apt-get purge ruby.
We’ll need git and curl to run the rbenv installer. Run the following to make sure they’re installed.
$ sudo apt-get install git curl
Run the rbenv installer.
$ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash
Add rbenv to your path by adding it to your
~/.bashrc. You’ll have to log out and log back in or
source ~/.bashrcfor the changes to take effect. (And we’re tackling 2 steps at once by including the
rbenv initline here.)
$ echo ' if [ -d "$HOME/.rbenv/bin" ]; then PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init - bash)" fi' >> ~/.bashrc
Check to make sure it worked with
rbenv-doctor. This will save you some headaches by printing errors if anything’s not quite right.
$ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-doctor | bash
You’ll see something like this, letting you know that rbenv is installed but no versions of Ruby are installed yet.
Counting installed Ruby versions: none There aren’t any Ruby versions installed under `/home/mkasberg/.rbenv/versions’. You can install Ruby versions like so: rbenv install 2.7.1
We’re going to use rbenv to install a version of Ruby, but before we do that we need to make sure we have the tools to build ruby installed. (If you skip this step, the installer won’t work and will give you an error message about what you need to install to compile Ruby. We can save time by just installing what we need now.)
$ sudo apt-get install build-essential libssl-dev libyaml-dev zlib1g-dev libffi-dev
Now, we’re ready to install Ruby. I like to run the help command first to see what I’m about to do. You should generally install whatever the latest stable version is. At the time of writing, it’s
$ rbenv help install $ rbenv install --list $ rbenv install 2.7.1
At this point, you’re basically done! Again, we can skim the help menu to see what other commands are available. And it’s a good idea to set the version we just installed as the global ruby version.
$ rbenv help $ rbenv global 2.7.1 $ rbenv version $ ruby --version
One thing that’s great about rbenv is it does not tie you in to a specific ruby
version. You can set up local
(per-directory) and shell (per-terminal) versions if you want. Simply
install x.x.x and then use the correct commands (see the docs) to pick your
version. In addition to this, by default, rbenv will allow you to install
gems to a location that
doesn’t require sudo (with a normal
gem install command), which should prevent
a lot of headaches.