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: 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: 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.