Skip to main content

Working with Provisioners

1. Using Shell Provisioner

Property Description Example
type Specifies the provisioner type. Must be shell. type = "shell"
path Path to the shell script file to execute. path = "scripts/setup.sh"
inline Inline shell commands to execute directly. inline = "echo 'Hello World'"
args Arguments to pass to the script or inline commands. args = ["arg1", "arg2"]
privileged Whether to run the script with elevated privileges (default: true). privileged = false
keep_file Whether to keep the script file on the guest machine (default: false). keep_file = true

Example: Basic Shell Provisioner

provisioner "shell" do
  inline "echo 'Provisioning started'"
end

Example: Using a Script File

provisioner "shell" do
  path "scripts/bootstrap.sh"
  args "--verbose"
end
Note: The shell provisioner runs on the guest machine and supports both inline scripts and external script files.

2. Inline Shell Scripts

Property Description Example
inline Defines the shell script to run directly in the Vagrantfile inline => "echo 'Hello from inline script'"
interpreter Specifies the interpreter to use for the inline script interpreter => "/bin/bash"

Example: Running an inline shell script

vagrant up
config.provisioner.shell do |shell|
  shell.inline = "echo 'Provisioning with inline script'"
end

Example: Using inline script with variables

vagrant up
config.provisioner.shell do |shell|
  shell.inline = "echo 'User: $USER'"
  shell.interpreter = "/bin/bash"
end

3. External Shell Scripts

Property Description Example
script Path to the external shell script file script = "provision.sh"
args Arguments to pass to the script args = ["--verbose", "--config"]

Example: Running an External Shell Script

config.vm.provision "shell", path: "scripts/setup.sh"

Example: Passing Arguments to Script

config.vm.provision "shell", path: "scripts/deploy.sh", args: ["--env", "production"]

4. Using Ansible Provisioner

Option Values Notes
ansible.playbook playbook.yml Path to the Ansible playbook file
ansible.verbose false Enable verbose output for debugging
ansible.limit all Limit the hosts to run the playbook on
ansible.extra_arguments --skip-tags=common Extra arguments to pass to the Ansible command

Example: Basic Vagrantfile with Ansible provisioner

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provision :ansible do |ansible|
    ansible.playbook = "playbook.yml"
  end
end

Example: Advanced Vagrantfile with Ansible provisioner

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provision :ansible do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.verbose = true
    ansible.limit = "web"
    ansible.extra_arguments = "--skip-tags=common --extra-vars=\"env=prod\""
  end
end
Note: Ensure Ansible is installed on the host machine and the Vagrant box has Python installed to run Ansible modules.

5. Configuring Ansible Playbook

Property Description Default Value Notes
ansible.playbook Path to the Ansible playbook file playbook.yml Must be a valid YAML file
ansible.verbose Enable verbose output for debugging false Set to true for detailed logs
ansible.limit Limit the hosts to run the playbook on null Accepts host patterns or groups
ansible.extra_vars Extra variables to pass to the playbook {} JSON object of variables

Example: Basic Ansible Playbook Configuration

Vagrant.configure("2") do |config|
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.verbose = true
  end
end

Example: Passing Extra Variables

Vagrant.configure("2") do |config|
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.extra_vars = {
      "app_env" => "production",
      "version" => "1.2.3"
    }
  end
end

6. Using Ansible Local

Property Description Default
ansible.local_playbook Path to the playbook file to run locally null
ansible.verbose Enable verbose output for Ansible runs false
ansible.debug Enable debug mode for Ansible runs false

Example: Basic Vagrantfile with Ansible Local

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provision :ansible_local do |ansible|
    ansible.playbook = "playbook.yml"
  end
end

Example: Advanced Vagrantfile with Ansible Local

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provision :ansible_local do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.verbose = true
    ansible.debug = false
  end
end
Note: The ansible.local_playbook path is relative to the Vagrantfile location.

7. Setting Up Chef Provisioner

Property Description Default Notes
chef_server_url URL of the Chef Server nil Required for Chef Server mode
chef_oauth_token OAuth token for authentication nil Required for Chef Server mode
chef_environment Environment to run the provisioner in _default Can be overridden
chef_node_name Name of the Chef node vagrant-<var>hostname</var> Automatically generated if not set
chef_run_list Run list of recipes to execute [] Must be an array of recipe names
chef_attributes Attributes to pass to Chef {} Hash of attribute key-value pairs

Example: Basic Chef Provisioner Configuration

config.vm.provision "chef_solo" do |chef|
  chef.run_list = [
    "recipe[myapp::default]"
  ]
  chef.attributes = {
    "myapp" => {
      "config_value" => "production"
    }
  }
end
Note: Chef Solo is deprecated in favor of Chef Infra Client. Use chef_client for newer setups.
Warning: Ensure the Chef server or client is properly configured and accessible from the Vagrant environment.

8. Configuring Puppet Provisioner

Option Values Description
provisioner puppet Specifies the provisioner type to use.
manifest_file manifest.pp Path to the main Puppet manifest file.
module_path modules/ Directory containing Puppet modules.
options --verbose Additional options to pass to the Puppet command.

Example: Basic Puppet Provisioner Configuration

config.vm.provision "puppet" do |puppet|
  puppet.manifest_file = "site.pp"
  puppet.module_path = ["modules", "site-modules"]
  puppet.options = "--verbose --debug"
end
Note: Ensure Puppet is installed on the guest machine or use a base box that includes it.

9. Using Docker Provisioner

Property Values Description
type docker Specifies the provisioner type as Docker
image ubuntu:20.04 Docker image to use for provisioning
container_name vagrant-docker-container Name of the container to create
command echo "Provisioning complete" Command to run inside the container

Example: Basic Docker Provisioner Configuration

# Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provision :docker do |d|
    d.image = "nginx:latest"
    d.container_name = "web-server"
    d.command = "echo 'Nginx is running'"
  end
end
Note: The Docker provisioner requires Docker to be installed on the host machine.
Warning: Ensure that the Docker image specified is accessible from the host machine.

10. Setting Provisioner Run Conditions

Condition Description Example
run Controls whether the provisioner runs. Valid values: "always", "once", "never". run = "once"
only_if Runs provisioner only if the specified command exits with code 0. only_if = "test -f /etc/myapp.conf"
unless Skips provisioner if the specified command exits with code 0. unless = "test -f /etc/myapp.conf"

Example: Using only_if and unless

config.vm.provision "shell", only_if: "test -f /etc/myapp.conf" do |s|
  s.inline = "echo 'Config file exists, running provisioner'"
end

config.vm.provision "shell", unless: "test -f /etc/myapp.conf" do |s|
  s.inline = "echo 'Config file missing, skipping provisioner'"
end

11. Using Multiple Provisioners

Vagrant allows you to define and run multiple provisioners in a single Vagrant environment. These provisioners can be of different types and are executed in the order they are defined.

Provisioner Type Description Execution Order Notes
shell Runs shell scripts on the guest machine Sequential Can be defined multiple times; each runs in order
ansible Uses Ansible playbooks to provision the guest Sequential Must be defined after shell provisioners if order matters
chef-solo Uses Chef Solo to configure the guest Sequential Can be mixed with other provisioners
puppet Uses Puppet to configure the guest Sequential Supports both manifest and module-based configurations

Example: Defining Multiple Provisioners

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  # Shell provisioner
  config.vm.provision :shell, inline: "echo 'Running shell provisioner'"

  # Ansible provisioner
  config.vm.provision :ansible do |ansible|
    ansible.playbook = "playbook.yml"
  end

  # Chef Solo provisioner
  config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = "cookbooks"
    chef.run_list = ["recipe[myapp::default]"]
  end

  # Puppet provisioner
  config.vm.provision :puppet do |puppet|
    puppet.manifest_file = "manifest.pp"
  end
end
Note: Provisioners are executed in the order they appear in the Vagrantfile. If you need to control execution order, ensure provisioners are defined in the correct sequence.

12. Setting Provisioner Order

Provisioner Type Execution Order Notes
shell 1 Executes first in the order
file 2 Executes after shell provisioners
template 3 Executes after file provisioners
puppet 4 Executes after template provisioners
ansible 5 Executes after puppet provisioners
chef 6 Executes after ansible provisioners
docker 7 Executes after chef provisioners
powershell 8 Executes after docker provisioners
Note: The order of provisioners is determined by their type, and can be overridden using the order attribute in the Vagrantfile.

Example: Setting Provisioner Order

Vagrant.configure("2") do |config|
  config.vm.provision "shell", inline: "echo 'First provisioner'"
  config.vm.provision "shell", inline: "echo 'Second provisioner", order: 2
  config.vm.provision "shell", inline: "echo 'Third provisioner", order: 1
end

Was this article helpful?