Shell provisioning inside a loop produces unexpected results

I want to create three VMs using single Vagrantfile. I also want to create a user and give that user sudo rights. The Vagrantfile below works, but the shell provisioning script appears to be run three times on each VM. Resulting in three lines added to `/etc/sudoers` rather than the one I was expecting. Is it not possible to use shell provisioning inside a loop like I've done?

The Vagrantfile:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagranyfile API/syntax version

Vagrant.require_version ">= 2.2.0"

# createVM function
# Function is required as Vagrant treats stuff inside the .confihure
# as a closure, and looping there causes weirdness.
def createVM(config, i)
config.vm.define "server#{i}" do |server|
server.vm.hostname = "server#{i}" = "generic/ubuntu1804"
server.vm.box_url = "generic/ubuntu1804" :private_network, ip: "{i}"

server.vm.provider :libvirt do |libvirt|
libvirt.memory = 1024
libvirt.cpus = 2

config.vm.provision :shell do |shell|
shell.path = 'vagrant/'

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
for i in 1..3 do
createVM(config, i)

And the script:


# apt-get update
# apt-get -y install git vim

if $(cat /etc/passwd | grep mark &> /dev/null) ; then
echo "User already exists"
useradd mark -s /bin/bash -m -G adm

chpasswd << 'END' mark:vagrant END # Add user mark to sudoers file echo 'mark ALL=(ALL:ALL) ALL' >> /etc/sudoers

1 thought on “Shell provisioning inside a loop produces unexpected results”

  1. I might be wrong but I don’t think all the VMs are being provsioned 3 times. I think the first one is being provisioned 3 times, the second VM 2 times, and the third 1 time. That’s because the provision step is using the `config` variable which belongs to all VMs. What you could do is use `run: “once” ` with the provision step.
    For a quick test, can you check the sudoers file on all 3 VMs?
    A quick fix could be to move the `chpasswd` and the `echo… ` commands into the `else` part right after you create the user to ensure that even if the provision script is executed multiple times, it will only call those commands once.


Leave a Comment