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
Written by Mike Hall
Related protips
5 Responses
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.
This question (http://stackoverflow.com/questions/24707986/create-linux-environment-variable-using-vagrant-provisioner) may help avoid the issue with running provisioning everytime.
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?
@Nickcom4 Try using vagrant file or install the vagrant plugin for scp
@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']"