54

I'm trying to install a rails app and every time I use bundle it fails without sudo. My current situation is that everything works as long as use sudo for everything, including rails. I don't think this is correct.

For example:

$ bundle update
Updating git://github.com/refinery/refinerycms.git
Fetching gem metadata from https://rubygems.org/.......
Fetching gem metadata from https://rubygems.org/..
Resolving dependencies...
Enter your password to install the bundled RubyGems to your system: 
Using rake (10.0.4) 
Using i18n (0.6.1) 
Using multi_json (1.7.2) 
Using rack-cache (1.2) 
Using rack-test (0.6.2) 
Installing hike (1.2.2) 
Errno::EACCES: Permission denied - /usr/local/rvm/gems/ruby-1.9.3-p194/build_info/hike-1.2.2.info
An error occurred while installing hike (1.2.2), and Bundler cannot continue.
Make sure that `gem install hike -v '1.2.2'` succeeds before bundling.

But then I do what it says and it works:

$ gem install hike -v '1.2.2' 
Successfully installed hike-1.2.2
Parsing documentation for hike-1.2.2
Installing ri documentation for hike-1.2.2
Done installing documentation for hike after 0 seconds
1 gem installed

This pattern repeats again and again for different gems. I don't get it. Why is this happening? If I use sudo bundle will update without this error. But the current situation is that I need sudo for everything, including rake... or rails server, etc. Something isn't right.

Additional details: I'm on OSX 10.8.3...

$ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0]
$ gem -v
2.0.3
$ rvm -v
rvm 1.19.6 (stable) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]

$ which ruby
/usr/local/rvm/rubies/ruby-1.9.3-p194/bin/ruby
$ which gem
/usr/local/rvm/rubies/ruby-1.9.3-p194/bin/gem
$ which rvm
/usr/local/rvm/bin/rvm

Update

It may be informative that I can run sudo bundle install with no errors. Then immediately after bundle install fails with an error like you see above. Why is this?

Update2

/usr/local/rvm[master]$ ls -l
total 56
-rw-rw-r--   1 root  rvm   566 May  4 12:59 LICENCE
-rw-rw-r--   1 root  rvm  8929 May  4 12:59 README
-rw-rw-r--   1 root  rvm     7 May  4 12:59 RELEASE
-rw-rw-r--   1 root  rvm     7 May  4 12:59 VERSION
drwxrwsr-x   3 root  rvm   102 May  4 01:34 archives
drwxrwsr-x  35 root  rvm  1190 May  4 12:59 bin
drwxrwsr-x  11 root  rvm   374 May  4 12:59 config
drwxrwsr-x   6 root  rvm   204 Jan 10 19:55 contrib
drwxrwsr-x   5 root  rvm   170 Jan 10 19:55 environments
drwxrwsr-x   3 root  rvm   102 Jan 10 19:55 examples
drwxrwsr-x   5 root  rvm   170 Jan 10 19:52 gems
drwxrwxr-x   6 ESL   rvm   204 May  4 12:59 gemsets
drwxrwsr-x  92 root  rvm  3128 May  4 01:34 help
drwxrwsr-x  11 root  rvm   374 May  4 01:34 hooks
-rw-rw-r--   1 root  rvm    11 May  4 12:59 installed.at
drwxrwsr-x   4 root  rvm   136 Jan 10 19:54 lib
drwxrwsr-x   5 root  rvm   170 May  4 12:55 log
drwxrwsr-x   2 root  rvm    68 Jan 10 19:52 man
drwxrwsr-x   9 root  rvm   306 Jan 10 19:52 patches
drwxrwxr-x   4 ESL   rvm   136 May  4 12:59 patchsets
drwxrwsr-x   4 root  rvm   136 Jan 10 19:55 rubies
drwxrwsr-x  64 root  rvm  2176 May  4 01:34 scripts
drwxrwsr-x   3 root  rvm   102 May  4 01:34 src
drwxrwsr-x   2 root  rvm    68 Jan 10 19:52 tmp
drwxrwsr-x   8 root  rvm   272 May  4 12:59 user
drwxrwsr-x   4 root  rvm   136 Jan 10 19:52 usr
drwxrwsr-x   5 root  rvm   170 Jan 10 19:55 wrappers
emersonthis
  • 32,822
  • 59
  • 210
  • 375

8 Answers8

77

You may host gems in your user home folder, that does not need root permissions:

bundle install --path ~/.gem

To avoid passing this parameter manually add export GEM_HOME=$HOME/.gem to your .bash_profile -- this solves sudo issue on Mac OS and other *nix systems. You then also might need to have access to gems that provide executables (such as bundler), so add this too:

PATH=$PATH:$HOME/.gem/bin

or in some cases:

PATH=$PATH:$HOME/.gem/ruby/<version>/bin

ref: https://stackoverflow.com/a/5862327/322020


UPD: But keep in mind that if you start using rbenv having this environment variable be the same might cause problems when using too different versions of Ruby, so you might want to temporary unset GEM_HOME or prepend custom one each time you launch rbenv-ed Ruby.

Community
  • 1
  • 1
Nakilon
  • 34,866
  • 14
  • 107
  • 142
  • this works with a ruby installed from debian packages, as well. – amenthes Aug 25 '15 at 21:59
  • 2
    you might want to add `~/.gem/ruby//bin` to your path in that case. – amenthes Aug 25 '15 at 22:01
  • Thanks, @amenthes . Added it to answer. – Nakilon Feb 09 '17 at 01:53
  • Using this, `bundle install` installs under versioned directory but `gem` installs under non-versioned directory. So gems installed by bundle are not visible by `gem`. How to make sure `gem` and `bundle` install in the same way? – akostadinov Oct 01 '20 at 20:13
  • @akostadinov, try `bundle exec gem install ...`. You can see that `gem list` and `bundle exec gem list` show different things. And `gem env` compared to `bundle exec gem env` too. The `bundle exec` makes the following command kind of run in another environment. Once you start using `bundle`, you should append it to other commands you run in this directory to make them work in the same environment. Some people who don't like to prepend `bundle exec` to everything prefer to use something like `require "bundler"` etc. in their Ruby code but I think it's messy. – Nakilon Oct 02 '20 at 00:43
  • @Nakilon, I see that `bundler` does not want to cooperate with `gem`, standard linux distribution conventions, nor any other tool. Prepending `bundle exec` is usually a good idea, in my situation though (not an indeal world situation) it is better to have bundle install in a `gem` compatible way. So I eventually figured that out https://stackoverflow.com/a/64163511/520567 – akostadinov Oct 02 '20 at 05:36
  • Instead of `bundle install --path ~/.gem` you'll probably need to do `bundle config set path '~/.gem'` which is the current way of setting the path, so that it's remembered without always having to specify the `path` flag. – SudoPlz Jan 11 '21 at 18:45
21

Your RVM gem directory should be owned by the rvm group. So, instead of changing ownership, it might be wise to simply add the user to the rvm group:

# $(whoami) evaluates to your username
# You may want to change this to a different username depending on your config
# but $(whoami) is a passable default
usermod -a -G rvm $(whoami)
OneChillDude
  • 7,856
  • 10
  • 40
  • 79
Matthew Clark
  • 1,885
  • 21
  • 32
10

tl;dr;

For 1.16.1

cd $HOME
bundle config path ~/.gem/ruby
cd my_project
bundle install

For 2.1.4 - I couldn't find a way except for creating a symlink after running Bundler.

For 2.2.0 - logic changed but still I couldn't find a way except for creating a symlink after running Bundler.

cd myproject
bundle install
ln -s `ruby -rbundler -e "puts Bundler.bundle_path"` `ruby -e "puts Gem.path[0]"`

Alternative - you can try gem install -g.

Explanation:

It turned out that at some point (I guess git blame can show it but I'm too lazy to check), bundler stopped installing gems as a user in the user local gem directory in a compatible way to gem install.

That means

  • gem install installs under ~/.gem/ruby/gems/gemname-gemversion
  • bundle install tries to install always to system dir and requires sudo
  • bundle install --path ~/.gem installs under ~/.gem/ruby/2.5.0/gems/gemname-gemversion /btw this flag seems to be deprecated since bundler 2.x/

There is no documentation how to request original behavior of installing the gems at the same place where gem does. Even documentation suggests that is already the case.

So looking at the source of .../gems/bundler-2.1.4/lib/bundler/settings.rb or .../gems/bundler-1.16.1/lib/bundler/settings.rb we can observe this gem (pun intended):

    # for legacy reasons, the ruby scope isnt appended when the setting comes from ENV or the global config,
    # nor do we respect :disable_shared_gems
    def path
      key  = key_for(:path)
      path = ENV[key] || @global_config[key]
      if path && !@temporary.key?(key) && !@local_config.key?(key)
        return Path.new(path, false, false, false)
      end

      system_path = self["path.system"] || (self[:disable_shared_gems] == false)
      Path.new(self[:path], true, system_path, Bundler.feature_flag.default_install_uses_path?)
    end

So we are looking at line if path && !@temporary.key?(key) && !@local_config.key?(key). This means path must be set but not in a temporary flag (I guess --path) and not in project local config. That means in user global config or as env variable.

That's why we need to go out of project directory and set the setting to the value it had by default anyway. But seeing this key present in user global config alters bundler behavior to install compatible with gem locally to the user without sudo.

cd
bundle config path ~/.gem/ruby

Thanks for following.

akostadinov
  • 17,364
  • 6
  • 77
  • 85
5

This is due to the way you installed ruby.

Frankly, it works *just fine* if you don't mind the sudo. At the end of the day, it's just your laptop... Not some server running in a bank.

If you really care, chown gem folders as needed.

Denis de Bernardy
  • 75,850
  • 13
  • 131
  • 154
  • 1
    I thought I installed Ruby using rvm, but I'm a total n00b so I may be confused. Can you elaborate slightly on how to chown the gem folders? Where are they? – emersonthis May 04 '13 at 17:55
  • 4
    `cd /path/to/gems`. And then `sudo chown -R username:groupname *`, where username and groupname are your own (on my system, that would be denis:staff; if you don't know yours, open Terminal and type `ls -l`). – Denis de Bernardy May 04 '13 at 17:57
  • Based on your questions, your gems are in `/usr/local/rvm/gems/` – Denis de Bernardy May 04 '13 at 17:58
  • I'll do this now. I also just noticed (after `ls -l`) that Gemfile.lock is owned by root. Every other file is owned by me. Is that weird? – emersonthis May 04 '13 at 17:59
  • That might be the culprit, for your follow-up question. – Denis de Bernardy May 04 '13 at 18:01
  • Just added another update. Looks like some of my gems are owned by me and others by root. Should that be the case? Do I want all of those to be owned by me? – emersonthis May 04 '13 at 18:03
  • I've read that RVM should not be installed as root with sudo. Is that what happened here? – emersonthis May 04 '13 at 18:04
  • They should all be owned by you. Re the other question, I've no idea TBH. I never bothered with RVM (I'm happy sudo'ing...), and Rails is something I gave up on around when I looked into RefineryCMS -- too messy imho. – Denis de Bernardy May 04 '13 at 18:08
  • I'm curious to know more about what you just said. Do you have a second to chat? – emersonthis May 04 '13 at 18:10
  • BTW. Recursive `chown` on the gems folders worked, in that I can now run `bundle install` without sudo. Thanks! – emersonthis May 04 '13 at 18:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/29421/discussion-between-denis-and-emerson) – Denis de Bernardy May 04 '13 at 18:18
  • What if this happens when you're setting up a webapp to a host where you don't have sudo access? – jk. May 26 '14 at 18:57
2

I had this happen today. This might be a unique situation, but I had copied a Rails source tree from a system that had RVM installed globally (system-wide in /usr/local/rvm), to a system that just had RVM installed per-user (~/.rvm).

I was trying to do bundle install and getting the "Your user account isn't allowed to install to the system Rubygems." error. After a lot of poking around, I noticed that in my ~/.rvm directory there was a symbolic link:

~/.rvm/gems/ruby-2.1.1/cache -> /usr/local/rvm/gems/cache

Removing that symlink got bundle install working again without sudo.

bjnord
  • 2,734
  • 2
  • 23
  • 24
1

I had the same problem and found out that Bundler before installing new gems checks if it has write permission for all files found $GEM_HOME/build_info. In my case it didn't, because although user that run bundler was in 'rvm' user group and that group owned all those files, group wasn't allowed to write some of them.

That happened because I installed some of the gems under root, which has umask 0022 (all files created by root, can't be written by group) instead of umask 0002 that others have and which rvm expects.

snovity
  • 488
  • 4
  • 11
1

The best fix for this seems to be to use rbenv for install ruby as follows -

rvm -v 
rvm list
rvm uninstall {version_to_uninstall}
rvm use system - Switch to macOS default ruby version
rvm implode - uninstall rvm 

rbenv - Ruby Environment Manager - we will use this to install ruby
brew install rbenv ruby-build
rbenv install 2.6.0

Add the following line to .bash_profile - 
if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi

source ~/.bash_profile
rbenv global 2.6.0
ruby -v 

Run rbenv rehash

rm -rf rbenv root /shims
rbenv rehash

Finally run -

bundle install
Arunabh Das
  • 13,212
  • 21
  • 86
  • 109
0

If you are using RVM, then do these two steps and you'll be golden

  1. Make sure your user belongs to the RVM group

    sudo usermod -a -G rvm myUserName

  2. Make sure build_info is writable for all users in the RVM group

    sudo chmod 664 $GEM_HOME/build_info/*

Darren Hicks
  • 4,946
  • 1
  • 32
  • 35