github.com/hugorut/terraform@v1.1.3/website/docs/language/resources/provisioners/syntax.mdx (about) 1 --- 2 page_title: Provisioners 3 description: >- 4 Provisioners run scripts on a local or remote machine during resource creation 5 or destruction. Learn how to declare provisioners in a configuration. 6 --- 7 8 # Provisioners 9 10 Provisioners can be used to model specific actions on the local machine or on 11 a remote machine in order to prepare servers or other infrastructure objects 12 for service. 13 14 ## Provisioners are a Last Resort 15 16 > **Hands-on:** To learn about more declarative ways to handle provisioning actions, try the [Provision Infrastructure Deployed with Terraform](https://learn.hashicorp.com/collections/terraform/provision?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) collection on HashiCorp Learn. 17 18 Terraform includes the concept of provisioners as a measure of pragmatism, 19 knowing that there will always be certain behaviors that can't be directly 20 represented in Terraform's declarative model. 21 22 However, they also add a considerable amount of complexity and uncertainty to 23 Terraform usage. Firstly, Terraform cannot model the actions of provisioners 24 as part of a plan because they can in principle take any action. Secondly, 25 successful use of provisioners requires coordinating many more details than 26 Terraform usage usually requires: direct network access to your servers, 27 issuing Terraform credentials to log in, making sure that all of the necessary 28 external software is installed, etc. 29 30 The following sections describe some situations which can be solved with 31 provisioners in principle, but where better solutions are also available. We do 32 not recommend using provisioners for any of the use-cases described in the 33 following sections. 34 35 Even if your specific use-case is not described in the following sections, we 36 still recommend attempting to solve it using other techniques first, and use 37 provisioners only if there is no other option. 38 39 ### Passing data into virtual machines and other compute resources 40 41 When deploying virtual machines or other similar compute resources, we often 42 need to pass in data about other related infrastructure that the software on 43 that server will need to do its job. 44 45 The various provisioners that interact with remote servers over SSH or WinRM 46 can potentially be used to pass such data by logging in to the server and 47 providing it directly, but most cloud computing platforms provide mechanisms 48 to pass data to instances at the time of their creation such that the data 49 is immediately available on system boot. For example: 50 51 * Alibaba Cloud: `user_data` on 52 [`alicloud_instance`](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance) 53 or [`alicloud_launch_template`](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/launch_template). 54 * Amazon EC2: `user_data` or `user_data_base64` on 55 [`aws_instance`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance), 56 [`aws_launch_template`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template), 57 and [`aws_launch_configuration`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration). 58 * Amazon Lightsail: `user_data` on 59 [`aws_lightsail_instance`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lightsail_instance). 60 * Microsoft Azure: `custom_data` on 61 [`azurerm_virtual_machine`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine) 62 or [`azurerm_virtual_machine_scale_set`](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine_scale_set). 63 * Google Cloud Platform: `metadata` on 64 [`google_compute_instance`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance) 65 or [`google_compute_instance_group`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance_group). 66 * Oracle Cloud Infrastructure: `metadata` or `extended_metadata` on 67 [`oci_core_instance`](https://registry.terraform.io/providers/hashicorp/oci/latest/docs/resources/core_instance) 68 or [`oci_core_instance_configuration`](https://registry.terraform.io/providers/hashicorp/oci/latest/docs/resources/core_instance_configuration). 69 * VMware vSphere: Attach a virtual CDROM to 70 [`vsphere_virtual_machine`](https://registry.terraform.io/providers/hashicorp/vsphere/latest/docs/resources/virtual_machine) 71 using the `cdrom` block, containing a file called `user-data.txt`. 72 73 Many official Linux distribution disk images include software called 74 [cloud-init](https://cloudinit.readthedocs.io/en/latest/) that can automatically 75 process in various ways data passed via the means described above, allowing 76 you to run arbitrary scripts and do basic system configuration immediately 77 during the boot process and without the need to access the machine over SSH. 78 79 > **Hands-on:** Try the [Provision Infrastructure with Cloud-Init](https://learn.hashicorp.com/tutorials/terraform/cloud-init?in=terraform/provision&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn. 80 81 If you are building custom machine images, you can make use of the "user data" 82 or "metadata" passed by the above means in whatever way makes sense to your 83 application, by referring to your vendor's documentation on how to access the 84 data at runtime. 85 86 This approach is _required_ if you intend to use any mechanism in your cloud 87 provider for automatically launching and destroying servers in a group, 88 because in that case individual servers will launch unattended while Terraform 89 is not around to provision them. 90 91 Even if you're deploying individual servers directly with Terraform, passing 92 data this way will allow faster boot times and simplify deployment by avoiding 93 the need for direct network access from Terraform to the new server and for 94 remote access credentials to be provided. 95 96 ### Running configuration management software 97 98 As a convenience to users who are forced to use generic operating system 99 distribution images, Terraform includes a number of specialized provisioners 100 for launching specific configuration management products. 101 102 We strongly recommend not using these, and instead running system configuration 103 steps during a custom image build process. For example, 104 [HashiCorp Packer](https://www.packer.io/) offers a similar complement of 105 configuration management provisioners and can run their installation steps 106 during a separate build process, before creating a system disk image that you 107 can deploy many times. 108 109 > **Hands-on:** Try the [Provision Infrastructure with Packer](https://learn.hashicorp.com/tutorials/terraform/packer?in=terraform/provision&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn. 110 111 If you are using configuration management software that has a centralized server 112 component, you will need to delay the _registration_ step until the final 113 system is booted from your custom image. To achieve that, use one of the 114 mechanisms described above to pass the necessary information into each instance 115 so that it can register itself with the configuration management server 116 immediately on boot, without the need to accept commands from Terraform over 117 SSH or WinRM. 118 119 ### First-class Terraform provider functionality may be available 120 121 It is technically possible to use the `local-exec` provisioner to run the CLI 122 for your target system in order to create, update, or otherwise interact with 123 remote objects in that system. 124 125 If you are trying to use a new feature of the remote system that isn't yet 126 supported in its Terraform provider, that might be the only option. However, 127 if there _is_ provider support for the feature you intend to use, prefer to 128 use that provider functionality rather than a provisioner so that Terraform 129 can be fully aware of the object and properly manage ongoing changes to it. 130 131 Even if the functionality you need is not available in a provider today, we 132 suggest to consider `local-exec` usage a temporary workaround and to also 133 open an issue in the relevant provider's repository to discuss adding 134 first-class provider support. Provider development teams often prioritize 135 features based on interest, so opening an issue is a way to record your 136 interest in the feature. 137 138 Provisioners are used to execute scripts on a local or remote machine 139 as part of resource creation or destruction. Provisioners can be used to 140 bootstrap a resource, cleanup before destroy, run configuration management, etc. 141 142 ## How to use Provisioners 143 144 -> **Note:** Provisioners should only be used as a last resort. For most 145 common situations there are better alternatives. For more information, see 146 the sections above. 147 148 If you are certain that provisioners are the best way to solve your problem 149 after considering the advice in the sections above, you can add a 150 `provisioner` block inside the `resource` block of a compute instance. 151 152 ```hcl 153 resource "aws_instance" "web" { 154 # ... 155 156 provisioner "local-exec" { 157 command = "echo The server's IP address is ${self.private_ip}" 158 } 159 } 160 ``` 161 162 The `local-exec` provisioner requires no other configuration, but most other 163 provisioners must connect to the remote system using SSH or WinRM. 164 You must include [a `connection` block](/language/resources/provisioners/connection) so that Terraform 165 will know how to communicate with the server. 166 167 Terraform includes several built-in provisioners; use the navigation sidebar to 168 view their documentation. 169 170 It's also possible to use third-party provisioners as plugins, by placing them 171 in `%APPDATA%\terraform.d\plugins`, `~/.terraform.d/plugins`, or the same 172 directory where the Terraform binary is installed. However, we do not recommend 173 using any provisioners except the built-in `file`, `local-exec`, and 174 `remote-exec` provisioners. 175 176 All provisioners support the `when` and `on_failure` meta-arguments, which 177 are described below (see [Destroy-Time Provisioners](#destroy-time-provisioners) 178 and [Failure Behavior](#failure-behavior)). 179 180 ### The `self` Object 181 182 Expressions in `provisioner` blocks cannot refer to their parent resource by 183 name. Instead, they can use the special `self` object. 184 185 The `self` object represents the provisioner's parent resource, and has all of 186 that resource's attributes. For example, use `self.public_ip` to reference an 187 `aws_instance`'s `public_ip` attribute. 188 189 -> **Technical note:** Resource references are restricted here because 190 references create dependencies. Referring to a resource by name within its own 191 block would create a dependency cycle. 192 193 ## Suppressing Provisioner Logs in CLI Output 194 195 The configuration for a `provisioner` block may use sensitive values, such as 196 [`sensitive` variables](/language/values/variables#suppressing-values-in-cli-output) or 197 [`sensitive` output values](/language/values/outputs#sensitive-suppressing-values-in-cli-output). 198 In this case, all log output from the provisioner is automatically suppressed to 199 prevent the sensitive values from being displayed. 200 201 ## Creation-Time Provisioners 202 203 By default, provisioners run when the resource they are defined within is 204 created. Creation-time provisioners are only run during _creation_, not 205 during updating or any other lifecycle. They are meant as a means to perform 206 bootstrapping of a system. 207 208 If a creation-time provisioner fails, the resource is marked as **tainted**. 209 A tainted resource will be planned for destruction and recreation upon the 210 next `terraform apply`. Terraform does this because a failed provisioner 211 can leave a resource in a semi-configured state. Because Terraform cannot 212 reason about what the provisioner does, the only way to ensure proper creation 213 of a resource is to recreate it. This is tainting. 214 215 You can change this behavior by setting the `on_failure` attribute, 216 which is covered in detail below. 217 218 ## Destroy-Time Provisioners 219 220 If `when = destroy` is specified, the provisioner will run when the 221 resource it is defined within is _destroyed_. 222 223 ```hcl 224 resource "aws_instance" "web" { 225 # ... 226 227 provisioner "local-exec" { 228 when = destroy 229 command = "echo 'Destroy-time provisioner'" 230 } 231 } 232 ``` 233 234 Destroy provisioners are run before the resource is destroyed. If they 235 fail, Terraform will error and rerun the provisioners again on the next 236 `terraform apply`. Due to this behavior, care should be taken for destroy 237 provisioners to be safe to run multiple times. 238 239 ``` 240 Destroy provisioners of this resource will not run if `create_before_destroy` 241 is set to `true`. We may address this in the future, and this [GitHub issue](https://github.com/hugorut/terraform/issues/13549) contains more details. 242 ``` 243 244 Destroy-time provisioners can only run if they remain in the configuration 245 at the time a resource is destroyed. If a resource block with a destroy-time 246 provisioner is removed entirely from the configuration, its provisioner 247 configurations are removed along with it and thus the destroy provisioner 248 won't run. To work around this, a multi-step process can be used to safely 249 remove a resource with a destroy-time provisioner: 250 251 * Update the resource configuration to include `count = 0`. 252 * Apply the configuration to destroy any existing instances of the resource, including running the destroy provisioner. 253 * Remove the resource block entirely from configuration, along with its `provisioner` blocks. 254 * Apply again, at which point no further action should be taken since the resources were already destroyed. 255 256 This limitation may be addressed in future versions of Terraform. For now, 257 destroy-time provisioners must be used sparingly and with care. 258 259 ~> **NOTE:** A destroy-time provisioner within a resource that is tainted _will not_ run. This includes resources that are marked tainted from a failed creation-time provisioner or tainted manually using `terraform taint`. 260 261 ## Multiple Provisioners 262 263 Multiple provisioners can be specified within a resource. Multiple provisioners 264 are executed in the order they're defined in the configuration file. 265 266 You may also mix and match creation and destruction provisioners. Only 267 the provisioners that are valid for a given operation will be run. Those 268 valid provisioners will be run in the order they're defined in the configuration 269 file. 270 271 Example of multiple provisioners: 272 273 ```hcl 274 resource "aws_instance" "web" { 275 # ... 276 277 provisioner "local-exec" { 278 command = "echo first" 279 } 280 281 provisioner "local-exec" { 282 command = "echo second" 283 } 284 } 285 ``` 286 287 ## Failure Behavior 288 289 By default, provisioners that fail will also cause the Terraform apply 290 itself to fail. The `on_failure` setting can be used to change this. The 291 allowed values are: 292 293 * `continue` - Ignore the error and continue with creation or destruction. 294 295 * `fail` - Raise an error and stop applying (the default behavior). If this is a creation provisioner, 296 taint the resource. 297 298 Example: 299 300 ```hcl 301 resource "aws_instance" "web" { 302 # ... 303 304 provisioner "local-exec" { 305 command = "echo The server's IP address is ${self.private_ip}" 306 on_failure = continue 307 } 308 } 309 ```