» Basic Usage of Provisioners

While Vagrant offers multiple options for how you are able to provisionyour machine, there is a standard usage pattern as well as some importantpoints common to all provisioners that are important to know.

» Configuration

First, every provisioner is configured within yourVagrantfileusing the config.vm.provision method call. For example, the Vagrantfilebelow enables shell provisioning:

  1. Vagrant.configure("2") do |config|
  2. # ... other configuration
  3. config.vm.provision "shell", inline: "echo hello"
  4. end

Every provisioner has a type, such as "shell", used as the firstparameter to the provisioning configuration. Following that is basic key/valuefor configuring that specific provisioner. Instead of basic key/value, youcan also use a Ruby block for a syntax that is more like variable assignment.The following is effectively the same as the prior example:

  1. Vagrant.configure("2") do |config|
  2. # ... other configuration
  3. config.vm.provision "shell" do |s|
  4. s.inline = "echo hello"
  5. end
  6. end

The benefit of the block-based syntax is that with more than a couple optionsit can greatly improve readability. Additionally, some provisioners, likethe Chef provisioner, have special methods that can be called within thatblock to ease configuration that cannot be done with the key/value approach,or you can use this syntax to pass arguments to a shell script.

The attributes that can be set in a single-line are the attributes thatare set with the = style, such as inline = "echo hello" above. If thestyle is instead more of a function call, such as add_recipe "foo", thenthis cannot be specified in a single line.

Provisioners can also be named (since 1.7.0). These names are used cosmetically for outputas well as overriding provisioner settings (covered further below). An exampleof naming provisioners is shown below:

  1. Vagrant.configure("2") do |config|
  2. # ... other configuration
  3. config.vm.provision "bootstrap", type: "shell" do |s|
  4. s.inline = "echo hello"
  5. end
  6. end

Naming provisioners is simple. The first argument to config.vm.provisionbecomes the name, and then a type option is used to specify the provisionertype, such as type: "shell" above.

» Running Provisioners

Provisioners are run in three cases: the initial vagrant up, vagrantprovision, and vagrant reload —provision.

A —no-provision flag can be passed to up and reload if you do notwant to run provisioners. Likewise, you can pass —provision to forceprovisioning.

The —provision-with flag can be used if you only want to run aspecific provisioner if you have multiple provisioners specified. Forexample, if you have a shell and Puppet provisioner and only want torun the shell one, you can do vagrant provision —provision-with shell.The arguments to —provision-with can be the provisioner type (such as"shell") or the provisioner name (such as "bootstrap" from above).

» Run Once, Always or Never

By default, provisioners are only run once, during the first vagrant upsince the last vagrant destroy, unless the —provision flag is set,as noted above.

Optionally, you can configure provisioners to run on every up orreload. They will only be not run if the —no-provision flag isexplicitly specified. To do this set the run option to "always",as shown below:

  1. Vagrant.configure("2") do |config|
  2. config.vm.provision "shell", inline: "echo hello",
  3. run: "always"
  4. end

You can also set run: to "never" if you have an optional provisionerthat you want to mention to the user in a "post up message" or thatrequires some other configuration before it is possible, then call thiswith vagrant provision —provision-with bootstrap.

If you are using the block format, you must specify it outsideof the block, as shown below:

  1. Vagrant.configure("2") do |config|
  2. config.vm.provision "bootstrap", type: "shell", run: "never" do |s|
  3. s.inline = "echo hello"
  4. end
  5. end

» Multiple Provisioners

Multiple config.vm.provision methods can be used to define multipleprovisioners. These provisioners will be run in the order they're defined.This is useful for a variety of reasons, but most commonly it is used sothat a shell script can bootstrap some of the system so that another provisionercan take over later.

If you define provisioners at multiple "scope" levels (such as globallyin the configuration block, then in amulti-machine definition, then maybein a provider-specific override),then the outer scopes will always run before any inner scopes. Forexample, in the Vagrantfile below:

  1. Vagrant.configure("2") do |config|
  2. config.vm.provision "shell", inline: "echo foo"
  3. config.vm.define "web" do |web|
  4. web.vm.provision "shell", inline: "echo bar"
  5. end
  6. config.vm.provision "shell", inline: "echo baz"
  7. end

The ordering of the provisioners will be to echo "foo", "baz", then"bar" (note the second one might not be what you expect!). Remember:ordering is outside in.

With multiple provisioners, use the —provision-with setting alongwith names to get more fine grained control over what is run and when.

» Overriding Provisioner Settings

Warning: Advanced Topic! Provisioner overriding isan advanced topic that really only becomes useful if you are alreadyusing multi-machine and/or provider overrides. If you are just gettingstarted with Vagrant, you can safely skip this.

When using features such as multi-machineor provider-specific overrides,you may want to define common provisioners in the global configurationscope of a Vagrantfile, but override certain aspects of them internally.Vagrant allows you to do this, but has some details to consider.

To override settings, you must assign a name to your provisioner.

  1. Vagrant.configure("2") do |config|
  2. config.vm.provision "foo", type: "shell",
  3. inline: "echo foo"
  4. config.vm.define "web" do |web|
  5. web.vm.provision "foo", type: "shell",
  6. inline: "echo bar"
  7. end
  8. end

In the above, only "bar" will be echoed, because the inline settingoverloaded the outer provisioner. This overload is only effectivewithin that scope: the "web" VM. If there were another VM defined,it would still echo "foo" unless it itself also overloaded theprovisioner.

Be careful with ordering. When overriding a provisioner ina sub-scope, the provisioner will run at that point. In the examplebelow, the output would be "foo" then "bar":

  1. Vagrant.configure("2") do |config|
  2. config.vm.provision "foo", type: "shell",
  3. inline: "echo ORIGINAL!"
  4. config.vm.define "web" do |web|
  5. web.vm.provision "shell",
  6. inline: "echo foo"
  7. web.vm.provision "foo", type: "shell",
  8. inline: "echo bar"
  9. end
  10. end

If you want to preserve the original ordering, you can specifythe preserve_order: true flag:

  1. Vagrant.configure("2") do |config|
  2. config.vm.provision "do-this",
  3. type: "shell",
  4. preserve_order: true,
  5. inline: "echo FIRST!"
  6. config.vm.provision "then-this",
  7. type: "shell",
  8. preserve_order: true,
  9. inline: "echo SECOND!"
  10. end