Mike Kasberg

Husband. Father. Software engineer. Ubuntu Linux user.

Image for How To Set Up a Ruby Dev Environment on Ubuntu Linux

How To Set Up a Ruby Dev Environment on Ubuntu Linux

27 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.

In a hurry?

Want to go straight to the instructions for the proper way (in my opinion) to install Ruby without reading about what not to do?

Skip ahead

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:

  1. Install Ruby

    $ sudo apt-get update && sudo apt-get install ruby
    
  2. Install the gem

    $ sudo gem install jekyll
    
  3. 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 sudo to 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 continue using 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 solution…

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.

  1. 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
    
  2. 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-install flag when we install our gem.

    $ gem install --user-install jekyll
    

    The --user-install portion 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.

  3. As the warning says, ~/.gem/ruby/2.7.1/bin isn’t in our PATH. So let’s put it there. Ubuntu comes with a ~/.profile file 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 ~/.gem/ruby/2.7.1/bin/jekyll.

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.

  1. 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
    
  2. Run the rbenv installer.

    $ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash
    
  3. Add rbenv to your path by adding it to your ~/.bashrc. You’ll have to log out and log back in or source ~/.bashrc for the changes to take effect. (And we’re tackling 2 steps at once by including the rbenv init line here.)

    $ echo '
    if [ -d "$HOME/.rbenv/bin" ]; then
        PATH="$HOME/.rbenv/bin:$PATH"
        eval "$(rbenv init - bash)"
    fi' >> ~/.bashrc
    
  4. 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

  5. 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
    
  6. 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 2.7.1.

    $ rbenv help install
    $ rbenv install --list
    $ rbenv install 2.7.1
    
  7. 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 rbenv 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.

About the Author

Mike Kasberg

👋 Hi, I'm Mike! I'm a husband, I'm a father, and I'm a senior software engineer at Strava. I use Ubuntu Linux daily at work and at home. And I enjoy writing about Linux, open source, programming, 3D printing, tech, and other random topics. I'd love to have you follow me on X or LinkedIn to show your support and see when I write new content!

Share!

If you enjoyed this blog post, I'd love it if you could share it with your network!

I run this blog in my spare time. There's no need to pay to access any of the content on this site, but if you find my content useful and would like to show your support, buying me a coffee is a small gesture to let me know what you like and encourage me to write more great content!

You can also support me by visiting LinuxLaptopPrices.com, a website I run as a side project.