Search code examples
rubymacosvagrantosx-yosemitevagrant-plugin

Cannot install vagrant plugins without sudo on OS X


I've installed plugins previously within vagrant. Now on a different MacBook, I'm trying to install some of the same plugins I was using on my older MacBook.

For example when I try to install vagrant-hostmanager I get a ruby permissions error:

$ vagrant plugin install vagrant-hostmanager
Installing the 'vagrant-hostmanager' plugin. This can take a few minutes...
Bundler, the underlying system Vagrant uses to install plugins,
reported an error. The error is shown below. These errors are usually
caused by misconfigured plugin installations or transient network
issues. The error from Bundler is:

An error occurred while installing ffi (1.9.8), and Bundler cannot continue.
Make sure that `gem install ffi -v '1.9.8'` succeeds before bundling.

Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

    /opt/vagrant/embedded/bin/ruby extconf.rb
checking for ffi.h... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/opt/vagrant/embedded/bin/ruby
    --with-ffi_c-dir
    --without-ffi_c-dir
    --with-ffi_c-include
    --without-ffi_c-include=${ffi_c-dir}/include
    --with-ffi_c-lib
    --without-ffi_c-lib=${ffi_c-dir}/
    --with-libffi-config
    --without-libffi-config
    --with-pkg-config
    --without-pkg-config
/opt/vagrant/embedded/lib/ruby/2.0.0/tmpdir.rb:92:in `mktmpdir': parent directory is world writable but not sticky (ArgumentError)
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:510:in `try_link0'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:534:in `try_link'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:427:in `have_devel?'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:433:in `try_do'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:549:in `block in try_compile'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:502:in `with_werror'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:549:in `try_compile'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:1044:in `block in have_header'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:895:in `block in checking_for'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:340:in `block (2 levels) in postpone'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:310:in `open'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:340:in `block in postpone'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:310:in `open'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:336:in `postpone'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:894:in `checking_for'
    from /opt/vagrant/embedded/lib/ruby/2.0.0/mkmf.rb:1043:in `have_header'
    from extconf.rb:16:in `<main>'


Gem files will remain installed in /Volumes/Passport/vagrant.d/gems/gems/ffi-1.9.8 for inspection.
Results logged to /Volumes/Passport/vagrant.d/gems/gems/ffi-1.9.8/ext/ffi_c/gem_make.out

One thing that is different is that as I'm tight on space on my local SSD, I've defined the following in my .bashrc:

export VAGRANT_HOME=/Volumes/Passport/vagrant.d

So my box files are stored on a 2TB USB3 drive instead of chewing up valuable SSD space.

Now I could execute the plugin install using sudo, but that becomes a cascading issue, in that vagrant up now cannot see the plugin within the Vagrantfile without doing sudo vagrant up. And then the VM is owned by root... you can see how this cascades out of control.

Anyone know what is wrong? How I might solve?

edit: I discovered that if I change my VAGRANT_HOME back to the default value of ~/.vagrant.d, I can install the plugin - however my boxes are now on a volume not accessible by the default setting. Apparently this is a Ruby limitation.

TIA!


Solution

  • Okay I found the problem to this, but unclear where the responsibility for fixing this lies - I'm thinking this is a Ruby bug on OS X (for at least the version embedded within Vagrant).

    Turns out Dir.mktmpdir expects the $TMPDIR variable to have the sticky bit set. On OS X the $TMPDIR variable points to unique per user directory like:

    /var/folders/yl/y9zbwwm951v3x6p62yn24ckw0000gn/T
    

    Changing the sticky bit using

    chmod +t $TMPDIR
    

    or really the more appropriate

    chmod 700 $TMPDIR
    

    Fixes this problem.

    Note: I'm not sure why or how my $TMPDIR got 777 permissions, I've checked other OS X 10.10 installs and found that $TMPDIR correctly has 700 permissions.