Last Updated: July 16, 2017
·
23.26K
· just3ws

Configure the Vagrant login user during provisioning using the Shell provider.

Vagrant allows for provisioning of new guest instances using Shell but the script is always run in the root context. Running as root is great for global configuration without having to deal with sudo. But, what do you do if you need to automatically configure the Vagrant login user during provisioning as well? That's not quite as straightforward as it might seem.

A skeleton of a typical project for me looks like:

 .
├── Vagrantfile
└── vagrant
    ├── provision.sh
    └── user-config.sh

The vagrant directory is not mandatory but is a convention I've adapted to organize all the files I'll be using for Vagrant but aren't related to the application logic. Most importantly there are two files present. The provision.sh is the file that holds all my global system configuration. The user-config.sh holds configuration specific to the vagrant login user.

My Vagrantfile will at a minimum be configured to use the Shell provisioner and kick off with the vagrant/provision.sh:

Vagrant.configure('2') do |config|
  # -- snipped --
  config.vm.provision :shell do |s|
    s.path = 'vagrant/provision.sh'
  end
  config.vm.synced_folder '.', '/home/vagrant/myapp'
  # -- snipped --
end

The provision.sh is responsible for all my root context actions like installing libraries or services such as Postgres, Redis, etc. This is all pretty typical of configuring a new system. What will be different though is that provision.sh will also invoke the user-config.sh as the vagrant user to set up custom configuration for whatever it is that I'll be doing. Typically I use the user-config.sh for installing RVM, installing my Ruby, Bundling Rubygems, then running the Rails and Rake tasks to setup my app.

An example of a minimal provision.sh for an Ubuntu guest system looks like:

#!/bin/bash -x

export DEBIAN_FRONTEND=noninteractive

apt-get update
apt-get -y install git
# install stuff, configure env, etc

su -c "source /home/vagrant/myapp/vagrant/user-config.sh" vagrant

Notice at the end that the provision.sh script there's a su command to execute the user-config.sh as the vagrant user.

#!/bin/bash -x

echo "export EDITOR=vim" >> $HOME/.bashrc

# RVM
echo "rvm_install_on_use_flag=1" >> $HOME/.rvmrc
echo "rvm_project_rvmrc=1"       >> $HOME/.rvmrc
echo "rvm_trust_rvmrcs_flag=1"   >> $HOME/.rvmrc
curl -L https://get.rvm.io | bash -s stable --autolibs=4
source "$HOME/.rvm/scripts/rvm"
[[ -s "$rvm_path/hooks/after_cd_bundle" ]] && chmod +x $rvm_path/hooks/after_cd_bundle
rvm autolibs enable
rvm requirements
rvm reload

_RUBY_VERSION="ruby-1.9.3"
rvm install $_RUBY_VERSION
rvm gemset create myapp
rvm use $_RUBY_VERSION --default
rvm use $_RUBY_VERSION@myapp

cd ~/myapp

gem update --system && gem update bundler
bundle config --global jobs 3

bundle install

bundle exec rake db:setup
bundle exec rake db:test:prepare

This can hold anything you require for your app. This is just an example of what I'm using for an app I'm currently working on.

One caveat is that the Shell provisioner will try to run every time you vagrant up. You'll need to change the way you start up Vagrant if you want to skip the provisioning step.

vagrant up --no-provision

5 Responses
Add your response

The solution to my issue is in here somewhere I think, but I can't quite put my finger on it. I have been left in the lurch by my developer and I'm new to Vagrant. It was working fine until I reloaded it (because I suddenly couldn't run rails runner commands). Now it's as if Rails isn't installed, even when I reinstall it. My issue is on stack overflow (http://stackoverflow.com/questions/29111177/vagrant-rails-not-installed). You, or someone else reading this, would be doing me a huge favour by posting an answer.

over 1 year ago ·

This question (http://stackoverflow.com/questions/24707986/create-linux-environment-variable-using-vagrant-provisioner) may help avoid the issue with running provisioning everytime.

over 1 year ago ·

Thanks for posing this information, it seems to be along the path I'm headed.
Your Vagrantfile snippet doesn't indicate how the user-config.sh file is move onto or generated on the guest machine. How do you complete this?

over 1 year ago ·

@Nickcom4 Try using vagrant file or install the vagrant plugin for scp

over 1 year ago ·

@codelinx Thanks for the tip. How do I get the script to run at the user level? I'm having difficulty configuring the user icons; the following code doesn't do anything when executed via vagrantfile. I always have to re-execute the code on the guest terminal.

gsettings set com.canonical.Unity.Launcher favorites "['application://org.gnome.Nautilus.desktop', 'application://chromium-browser.desktop', 'unity://running-apps', 'application://terminator.desktop', 'unity://expo-icon', 'unity://devices']"

over 1 year ago ·