86

There are some commands that have to be run as a normal user after the initial provisioning. I thought I could do this using a separate shell script and the command su --login -c <command> vagrant, but it's not getting the user's path or other environment settings from .bashrc.

e.g.:

#!/usr/bin/env bash
su --login -c "rbenv install 2.0.0-p353" vagrant
su --login -c "rbenv global 2.0.0-p353" vagrant
su --login -c "gem update --system" vagrant
su --login -c "yes | gem update" vagrant
su --login -c "gem install rdoc" vagrant
su --login -c "gem install rails pg" vagrant

Is there a way to do this? Maybe it has to be done with another provisioning tool like Puppet or Chef? I've thought of creating another shell script that sources the .bashrc, copying it to the box using a :file provisioner and executing the commands like that, but it seems sort of like a hack.

What's the right way to do this?

Vince
  • 3,962
  • 3
  • 33
  • 58
  • `su -p` will preserve environment variables - does this help? – Josh Jolly Mar 21 '14 at 10:37
  • @Vince I think it will be prefect to your question to mention about build `Vagrant` box with Ruby installation, add `Ruby` tag and append Ruby Installation on question's title Like this => execute Ruby installation commands as user during Vagrant provisioning – ahmed hamdy Jul 28 '19 at 03:47

4 Answers4

169

You should be able to do this using the Vagrant Shell provisioner, e.g.

Vagrant.configure("2") do |config|
  $script = <<-SCRIPT
  rbenv install 2.0.0-p353
  rbenv global 2.0.0-p353
  gem update --system
  yes | gem update
  gem install rdoc
  gem install rails pg
  SCRIPT

  config.vm.provision "shell", inline: $script, privileged: false
end

The key is to specify privileged: false so that it will use the default user and not root.

Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380
jabclab
  • 14,786
  • 5
  • 54
  • 51
7

I wanted to document a solution for situations where the shell provisioner must run commands as a non-root user in a login shell:

Put your provisioning commands into a shell script (e.g. 'bootstrap.sh'):

#! /bin/bash

rbenv install 2.0.0-p353
rbenv global 2.0.0-p353
gem update --system
yes | gem update
gem install rdoc
gem install rails pg

Then in your Vagrantfile:

Vagrant.configure(2) do |config|

  $script = "/bin/bash --login /vagrant/bootstrap.sh"
  config.vm.provision :shell, privileged: false, inline: $script

end

You should replace the /vagrant/bootstrap.sh path with the correct path for your provisioning script inside the vagrant machine.

I've used this solution specifically to get rvm commands to work while provisioning with Vagrant.

Daniel
  • 2,744
  • 1
  • 31
  • 41
evanhsu
  • 303
  • 3
  • 6
2

Sometimes you want to mix privileged commands and non-privileged commands. If your situation calls for this use runuser.

runuser -l vagrant -c 'command'

Chris Godwin
  • 129
  • 2
  • 3
  • I was trying to install `nvm` as part of the Vagrantfile. the default script would install it for root but not the `vagrant` user. This did the trick without having to write a shell script. – Joe Jacobs Jan 23 '21 at 03:36
1

I tried Both @jabclab and @evanhsu answers not work with me

To install rbenv and use it within Vagrant Provisioning process.

Using Next Commands before using rbenv commands

export PATH="$HOME/.rbenv/bin:$PATH"
export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"
eval "$(rbenv init -)"

Bootstrap.sh File

#!/usr/bin/env bash

sudo apt-get update
echo "========================= install dependencies for install rbenv ==========================="
sudo apt-get install -y autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
echo "========================= install rbenv =========================================="
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >>  ~/.bashrc
echo 'eval "$(rbenv init -)"' >>  ~/.bashrc
echo "========================= install ruby build plugin for rbenv ======================="
git clone https://github.com/rbenv/ruby-build.git  ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
echo "========================= install ruby v2.5.0 =========================================="
export PATH="$HOME/.rbenv/bin:$PATH"
export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"
eval "$(rbenv init -)"
rbenv install 2.5.0
rbenv global 2.5.0
ruby -v
gem -v
echo "========================= install bundler dependencies manager for ruby ====================="
gem install bundler
rbenv rehash

Then VagrantFile file will include vagrant provisioning line

deploy_config.vm.provision :shell, privileged: false, path: "bootstrap.sh"

Source for my Answer from Gits by @creisor

Another Way to using rbenv commands within vagrant provisioning process at answers of this question

ahmed hamdy
  • 5,096
  • 1
  • 47
  • 58