Terraform
resource block reference
The resource
block defines a piece of infrastructure and specifies the settings for Terraform to create it with. The arguments that an individual resource supports are determined by the provider. Refer to the provider documentation for more information about specific resource configuration.
Configuration model
The resource
block supports the following arguments:
resource "<TYPE>" "<LABEL>"
blockPROVIDER ARGUMENTS
block | refer to your provider documentationcount
number | mutually exclusive withfor_each
depends_on
list of referencesfor_each
map or set of strings | mutually exclusive withcount
provider
referencelifecycle
blockcreate_before_destroy
booleanprevent_destroy
booleanignore_changes
list of attributesreplace_triggered_by
list of referencesprecondition
blockcondition
stringerror_message
string
postcondition
blockcondition
stringerror_message
string
connection
blocktype
stringuser
stringpassword
stringhost
stringport
stringtimeout
stringscript_path
stringprivate_key
stringcertificate
stringagent
stringagent_identity
stringhost_key
stringtarget_platform
stringscript_path
stringhttps
stringinsecure
stringuse_ntlm
stringcacert
stringbastion_host
stringbastion_host_key
stringbastion_port
stringbastion_user
stringbastion_password
stringbastion_private_key
stringbastion_certificate
stringproxy_scheme
stringproxy_port
stringproxy_user_name
stringproxy_user_password
string
provisioner "<TYPE>"
blocksource
stringdestination
stringcontent
stringcommand
stringworking_dir
stringinterpreter
stringenvironment
stringwhen
keywordquiet
booleaninline
list of stringsscript
stringscripts
stringon_failure
keywordconnection
block
Complete configuration
The following resource
block defines all of the supported built-in arguments you can set on a resource:
resource "<TYPE>" "<LABEL>" {
<PROVIDER_ARGUMENTS>
count = <NUMBER> # `for_each` and `count` are mutually exclusive
depends_on = [ <RESOURCE.ADDRESS.EXPRESSION> ]
for_each = { # `for_each` and `count` are mutually exclusive
<KEY> = <VALUE>
}
for_each = [ # `for_each` accepts a map or a set of strings
"<VALUE>",
"<VALUE>"
]
provider = <REFERENCE.TO.ALIAS>
lifecycle {
create_before_destroy = <true || false>
prevent_destroy = <true || false>
ignore_changes = [ <ATTRIBUTE> ]
replace_triggered_by = [ <RESOURCE.ADDRESS.EXPRESSION> ]
precondition {
condition = <EXPRESSION>
error_message = "<STRING>"
}
postcondition {
condition = <EXPRESSION>
error_message = "<STRING>"
}
}
connection {
type = <"ssh" or "winrm">
host = <EXPRESSION>
<DEFAULT_CONNECTION_SETTINGS>
}
provisioner "<TYPE>" {
source = "<PATH>"
destination = "<PATH>"
content = "<CONTENT TO COPY TO `destination`>"
command = <COMMAND>
working_dir = "<PATH TO DIR WHERE TERRAFORM EXECUTES `command`>"
interpreter = [
"<PATH TO INTERPRETER EXECUTABLE>",
"<COMMAND> <ARGUMENTS>"
]
environment {
"<KEY>" = "<VALUE>"
}
when = <TERRAFORM COMMAND>
quiet = <true || false>
inline = [ "<COMMAND>" ]
script = "<PATH>"
scripts = [
"<PATH>"
]
on_failure = <continue || fail>
connection {
type = <"ssh" or "winrm">
host = <EXPRESSION>
<SPECIFIC_CONNECTION_SETTINGS>
}
}
}
Specification
A resource
block supports the following configuration.
resource "<TYPE>" "<LABEL>"
You must set the following arguments for every resource
block:
TYPE
: Specifies the type of resource to create. You can declare either a resource type determined by the provider or the built-interraform_data
resource type, which stores values and triggers Terraform operations without creating actual infrastructure. For information about provider resource types, refer to the provider documentation.LABEL
: Specifies a name for the resource. Terraform uses this label to track the resource in your state file. The label does not affect settings on the actual infrastructure resource. Refer to References to Named Values and Resource naming for expression syntax and label recommendations.
To reference the resource in your configuration, you must refer to it using <TYPE>.<LABEL>
syntax.
PROVIDER ARGUMENTS
The provider developer determines which arguments you can define for a resource. Refer to the provider documentation for details.
count
The count
meta-argument instructs Terraform to provision multiple instances of the same resource with identical or similar configuration.
resource {
count = <number>
}
The value must be a whole number. You can reference variables or local values and use expressions to compute the value, but the value must resolve to a whole number.
In blocks where count
is set, Terraform exposes an additional count
object. You can reference the object to modify the configuration of each instance. The count
object has an index
attribute starting from 0
.
To refer to an individual instance of a resource created using the count
meta-argument, use the <TYPE>.<NAME>[INDEX]
syntax. For example, aws_instance.server[0]
refers to the first instance of the aws_instance
resource named server
.
Tip
You can use the count
argument as a conditional for creating resources. For example, setting a count = var.creator ? 3 : 0
instructs Terraform to create three instances of the resource when a variable named creator
is set to true
. Refer to Conditional Expressions for more information.
The count
argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: Number.
- Default: None.
- Example: Create multiple instances of a resource.
depends_on
The depends_on
meta-argument specifies an upstream resource that the resource depends on. Terraform must complete all operations on the upstream resource before performing operations on the resource containing the depends_on
argument.
resource {
depends_on = [ <resource reference> ]
}
When a resource configuration refers to another resource, Terraform identifies the dependency and creates the upstream resource first. In some cases, you may need Terraform to create a resource before creating another, even though the resources are configured independently.
Use the depends_on
argument when the resources do not reference each other. We recommend always including a comment to explain resource dependencies when using a depends_on
argument.
When using the depends_on
meta-argument, you can only reference other resources or child modules in the same root module. The list cannot include arbitrary expressions. Any values referenced in the depends_on
list must be known before Terraform begins the operation so that it can evaluate dependencies.
Specifying an entire module in the depends_on
argument affects the order in which Terraform provisions all of the resources and data sources associated with that module. Refer to Resource dependencies
and Data resource dependencies for more information.
The depends_on
argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: List.
- Default: None.
- Example: Specify a dependency.
for_each
The for_each
meta-argument instructs Terraform to provision similar resources without requiring separate configuration blocks for each resource.
resource {
for_each = [ "<VALUE>" ]
# . . .
}
The for_each
meta-argument accepts a map or a set of strings and creates an instance for each item in that map or set. Each instance is associated with a distinct infrastructure object. Terraform creates, updates, or destroys each instance when applying changes to the configuration.
You can use pure functions, such as toset()
and tomap()
, to create a map or set for use in the for_each
argument. Whether iterating over the keys of a map or set of strings, all must be known values. Otherwise, Terraform prints an error message that for_each
has dependencies that it cannot determine before applying the configuration.
Keys in the for_each
argument cannot be the result of or rely on the result of impure functions, including uuid
, bcrypt
, or timestamp
, because Terraform defers evaluating impure functions during the main evaluation step.
The for_each
argument does not implicitly convert lists or tuples to sets. To declare resource instances based on a nested data structure or combinations of elements from multiple data structures, you can use Terraform expressions and functions to derive a suitable value. Refer to the following examples for more information:
- Transform a multi-level nested structure into a flat list.
- Combine collections to produce a list of element combinations.
You cannot use sensitive values, such as sensitive input variables, sensitive outputs, or sensitive resource attributes, as arguments in for_each
. Terraform uses the value in for_each
to identify the resource instance and always discloses it in UI output, so sensitive values are not allowed. Terraform returns an error if you attempt to use sensitive values as for_each
arguments.
If you transform a value containing sensitive data into an argument for use in for_each
, be aware that most functions in Terraform will return a sensitive result if given an argument with any sensitive content. In many cases, you can achieve similar results with a for
expression. For example, to call keys(local.map)
where local.map
is an object with sensitive values, but non-sensitive keys, you can create a value to pass to for_each
using toset([for k,v in local.map : k])
.
Refer to Manage sensitive data for more information.
The for_each
argument exposes an each
object that you can reference within the same block to modify specific instances of the resource. The object has the following attributes:
each.key
: Map key or list member that corresponds to an instance.each.value
: Map value that corresponds to an instance.
Use the <TYPE>.<NAME>[<KEY>]
syntax to access an instance of a resource created using for_each
. For example, azurerm_resource_group.rg["a_group"]
refers to an instance of the azurrm_resource_group
resource named rg
created off of the a_group
key.
The for_each
argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: Map or set of strings.
- Default: None.
- Example: Create multiple instances of a resource.
provider
The provider
argument instructs Terraform to use an alternate provider configuration to provision the resource.
resource {
provider = <provider>.<alias>
}
By default, Terraform automatically selects a provider based on the resource type, but you can create multiple provider configurations and use a non-default configuration for specific resources.
Use the <PROVIDER>.<ALIAS>
syntax to reference a provider configuration in the provider
argument.
The provider
argument is a meta-argument, which is built into Terraform and controls the way that Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: Reference.
- Default: None.
- Example: Select an alternate provider configuration.
lifecycle
The lifecycle
block defines lifecycle rules that instruct Terraform when and how to operate on your resource.
resource {
lifecycle {
<lifecycle>
}
}
You can specify the following lifecycle rules to manage how Terraform performs operations on the resource:
create_before_destroy
: Terraform creates a replacement resource before destroying the current resource.prevent_destroy
: Terraform rejects operations to destroy the resource and returns an error.ignore_changes
: Specifies a list of resource attributes that Terraform ignores changes to. Otherwise, Terraform attempts to update the actual resource to match the configuration.replace_triggered_by
: Terraform replaces the resource when any of the referenced resources or specified attributes change.precondition
: Specifies a condition that Terraform evaluates before creating the resource. Refer to Validate your configuration for more information.postcondition
: Specifies a condition that Terraform evaluates after creating the resource. Refer to Validate your configuration for more information.
Configurations defined in the lifecycle
block affect how Terraform constructs and traverses the dependency graph. You can only use literal values in the lifecycle block because Terraform processes them before it evaluates arbitrary expressions for a run.
The lifecycle
block is a meta-argument. Meta-arguments are built-in arguments that control how Terraform creates resources. Refer to Meta-arguments for more information.
Summary
- Data type: Block.
- Default: None
create_before_destroy
The create_before_destroy
argument instructs Terraform to create a replacement resource before destroying the resource it replaces.
resource {
lifecycle {
create_before_destroy = <boolean>
}
}
By default, Terraform destroys a resource before creating a replacement.
Refer to the documentation for the resource type you are configuring to understand which changes Terraform can make in-place and which require recreating the resource to decide whether to use the create_before_destroy
argument.
Terraform propagates and applies the create_before_destroy
behavior to all resource dependencies. For example, if create_before_destroy
is enabled on resource A but not on resource B, but resource A is dependent on resource B, then Terraform enables create_before_destroy
for resource B implicitly and records it in the state file. You cannot override create_before_destroy
to false
on resource B because that would imply dependency cycles in the graph.
Settingcreate_before_destroy
to true
on a resource stops any configured destroy provisioners.
Summary
- Data type: Boolean
- Default: None.
prevent_destroy
The prevent_destroy
argument instructs Terraform to reject plans to destroy the resource.
resource {
lifecycle {
prevent_destroy = <boolean>
}
}
Use this argument to prevent team members from accidentally replacing critical infrastructure, such as database instances.
When the prevent_destroy
argument is set, you must either remove the resource from the configuration or change the prevent_destroy
argument to false
to destroy it. Use this argument with caution. The prevent_destroy
argument can make applying resource changes or destroying resources more complex.
Summary
- Data type: Boolean.
- Default: None.
ignore_changes
The ignore_changes
argument specifies a list of resource attributes for Terraform to ignore when planning updates to the resource.
resource {
lifecycle {
ignore_changes = [ <attribute> ]
}
}
Use this argument when the resource references data that may change but does not affect the resource after its creation.
By default, Terraform detects any difference in the current settings of a real infrastructure object and plans to update the remote object to match the configuration.
Terraform uses the specified arguments to create a resource, but ignores them when planning an update
operation. You can specify arguments as the relative attribute addresses in the resource and reference members of maps and lists using index notation, such as tags["Name"]
and list[0]
.
You can also specify all
instead of a list to ignore future changes to all resource attributes. This lets Terraform create and destroy the resource but it does not propose updates to it.
Summary
- Data type: List.
- Default: None.
- Example: Ignore attribute changes.
replace_triggered_by
The replace_triggered_by
argument instructs Terraform to replace the resource when any of the referenced items change.
resource {
lifecycle {
replace_triggered_by = [ <address.reference> ]
}
}
You can specify a list of expressions that reference managed resources, instances, or instance attributes. You can only reference managed resources in replace_triggered_by
expressions. This lets you modify these expressions without forcing replacement.
The trigger is based on the planned actions for all of the given resources. Terraform does not plan actions for plain values, such as local values or input variables, but you can use the terraform_data
resource type to apply a resource-like lifecycle to them.
References in the argument list trigger a replacement under following conditions:
- When referencing a resource with multiple instances, such as those created by
count
orfor_each
, aterraform plan
command to update or replace any instance triggers replacement. - When referencing a single resource instance, a
terraform plan
command to update or replace that instance triggers replacement. - When referencing a single attribute of a resource instance, any change to the attribute value triggers replacement.
Adding the replace_triggered_by
argument to a resource that uses count
or for_each
lets you add the count.index
or each.key
resource address to the expression. Use this address segment to reference specific instances of other resources that are configured with the same count
or collection.
Summary
- Data type: List
- Default: None.
- Example: Specify triggers that replace resources
precondition
The precondition
block specifies a condition that must return true
before Terraform evaluates and performs operations on the resource. You can also specify an error message for Terraform to print when the condition returns false
.
resource {
lifecycle {
precondition {
condition = <expression>
error_message = "<message>"
}
}
}
The following arguments in the precondition
block are required:
Argument | Description | Data type |
---|---|---|
condition | Expression that must return true for Terraform to proceed with an operation. You can refer to any other object in the same configuration scope unless the reference creates a cyclic dependency. | Expression that can include references, strings, and operators. |
error_message | Message that Terraform prints to the console if the condition returns false . | String |
Terraform evaluates precondition
blocks before evaluating the resource's configuration arguments. The precondition
can take precedence over argument evaluation errors.
Terraform evaluates precondition blocks after evaluating count
and for_each
meta-arguments. As a result, Terraform can evaluate the precondition
separately for each instance and makes the each.key
and count.index
objects available in the conditions.
You can include a precondition
and postcondition
block in the same resource. Do not add precondition
blocks to a resource
block and a data
block that represent the same object in the same configuration. Doing so can prevent Terraform from understanding that the data block result can be affected by changes in the resource block.
Refer to Validate your configuration for information about adding validations to your Terraform configuration.
Summary
- Data type: Block.
- Default: None.
- Example: Apply custom conditions
postcondition
The postcondition
block specifies a condition that must return true
after Terraform performs operations on the resource. You can also specify an error message for Terraform to print to the console when the condition returns false
.
resource {
lifecycle {
postcondition {
condition = <expression>
error_message = "<message>"
}
}
}
The following arguments in the precondition
block are required:
Argument | Description | Data type |
---|---|---|
condition | Expression that must return true for Terraform to perform operations on downstream resources. You can refer to any other object in the same configuration scope unless the reference creates a cyclic dependency. | Expression that can include references, strings, and operators. |
error_message | Message that Terraform prints to the console if the condition returns false . | String |
Refer to Validate your configuration for information about adding validations to your Terraform configuration.
Terraform evaluates postcondition
blocks after planning and applying changes to the resource. Postcondition failures prevent changes to other resources that depend on the failing resource.
You can include a postcondition
and precondition
block in the same resource. Do not add postcondition
blocks to a resource
block and a data
block that represent the same object in the same configuration. Doing so can prevent Terraform from understanding that the data block result can be affected by changes in the resource block.
Summary
- Data type: Block.
- Default: None.
- Example: Apply custom conditions
connection
The connection
block specifies settings that let provisioners connect to resources so that Terraform can perform operations on the resource after creating it.
Warning
We recommend using configuration management tools or other means to perform actions on the local or remote machine instead of using provisioners. Refer to Perform post-apply action for more information.
You can add the connection
block to either the resource
block or the provisioner
block. When added to the resource
block, the connection
block sets default connection settings for all provisioners defined in the resource so that provisioners can connect to the remote resource after Terraform provisions it.
resource {
# . . .
connection {
<settings for all provisioners in the resource>
}
}
When added to a provisioner
block, the connection
block defines settings specific to the provisioner.
resource {
# . . .
provisioner {
# . . .
connection {
<settings for all provisioners in the resource>
}
}
}
Terraform does not validate SSH host keys by default. You can establish a separate mechanism for key distribution and explicitly set the host_key
argument to verify against a specific key or signing CA.
You can use ephemeral values for arguments in the connection
block. Refer to Manage sensitive data for more information.
Expressions in connection
blocks cannot refer to their parent resource by name. References create dependencies, and referring to a resource by name within its own block would create a dependency cycle. Instead, use the self
object in expressions to refer to the connection
block's parent block, including all of its attributes. For example, use self.public_ip
to reference the public_ip
attribute in an aws_instance
.
Tip
You can provide multiple connections so that an initial provisioner can connect as the root user to set up user accounts and subsequent provisioners can connect as less-privileged users to perform more specific operations.
The following table describes the arguments you can use in the connection
block:
Argument | Description | Data type | Connection | Default |
---|---|---|---|---|
type | Specifies the type of connection for sending and receiving data from the remote resource. You can specify ssh or winrm . When set to winrm , provisioners implement Windows-specific behaviors, even when target_platform is set to unix , unless otherwise specified. | string | ssh | |
user | Specifies the user to use for the connection. | string | ssh
|
|
password | Specifies the password to use for the connection. | string | ssh
| none |
host | Specifies the address of the resource to connect to. This argument is required. | string | ssh
| none |
port | Specifies the port number to connect to. | number | ssh
|
|
timeout | Specifies how long to wait for the connection to become available. | string | ssh
| "5m" |
script_path | Specifies the path on the remote resource where Terraform copies scripts to. Refer to the provisioner block reference for more information. Terraform copies scripts to a path that contains random numbers depending on the target_platform configuration. | string | ssh
|
|
private_key | Specifies the contents of an SSH key to use for the connection. private_key takes precedence over password when both are provided. | string Use a | ssh | none |
certificate | Specifies the contents of a signed CA certificate. You must also configure a private_key arugment. | string Use a | ssh | none |
agent | Specifies an SSH agent for authentication. Set to false to disable using ssh-agent to authenticate. On Windows, the only supported SSH authentication agent is Pageant. | string | ssh | false |
agent_identity | Specifies the preferred identity from the SSH agent to use for authentication. | string | ssh | none |
host_key | Specifies the public key from the remote host or the signing CA to verify the connection. | string | ssh | none |
target_platform | Specifies the target platform, which affects the default value for the script_path argument. You can specify either windows or unix .
| string | ssh | unix |
https | Set to true to connect using HTTPS instead of HTTP. | boolean | winrm | false |
insecure | Set to true to skip validating the HTTPS certificate chain. | boolean | winrm | false |
use_ntlm | Set to true to use NTLM authentication instead of basic authentication. Using NTLM removes the requirement for basic authentication to be enabled within the target guest. Refer to Authentication for Remote Connections in the Windows App Development documentation for more details. | boolean | winrm | false |
cacert | Specifies the CA certificate to validate against. | string | winrm | none |
bastion_host | Specifies the address of the bastion host. The provisioner connects to bastion_host before connecting to host . | string | ssh | none |
bastion_host_key | Specifies the public key from the remote host or the signing CA to verify the host connection. | string | ssh | none |
bastion_port | Specifies the port number to use for the bastion host connection. | string | ssh | value of the port field |
bastion_user | Specifies the user name for connecting to the bastion host. | string | ssh | value of the user field |
bastion_password | Specifies the user password for connecting to the bastion host. | string | ssh | value of the password field |
bastion_private_key | Specifies the contents of an SSH key file to use for the bastion host. | string Use a | ssh | value of the private_key field |
bastion_certificate | Specifies the contents of a signed CA certificate. You must also configure the bastion_private_key argument when providing the certificate for the bastion host. | string Use a | ssh | value of the certificate field |
proxy_scheme | Specifies the connection protocol. You can specify one of the following values: http https socks5 | string | ssh | none |
proxy_host | Specifies the address of the proxy host. The provisioner connects to the proxy host first. When bastion_host is configured, the provisioner connects to the bastion host next, otherwise the provisioner connects to the host specified in the host argument. | string | ssh | none |
proxy_port | Specifies the port number to use for the proxy host connection. | number | ssh | none |
proxy_user_name | Specifies the user name for connecting to the proxy host. You should only configure this argument when the proxy server requires authentication. | string | ssh | none |
proxy_user_password | Specifies the user password for connecting to the proxy host. You should only configure this argument when the proxy server requires authentication. | string | ssh | none |
Summary
- Data type: Block.
- Default: None.
- Example: Connect to remote resources
provisioner
The provisioner
block defines actions to perform on the local machine or created resource, such as preparing servers or other infrastructure objects for service.
resource {
provisioner "<TYPE>" {
<arguments>
}
}
Warning
We recommend using configuration management tools or other means to perform actions on the local or remote machine instead of using the provisioner
block. Refer to Perform post-apply action for more information.
The provisioner
block supports the following arguments:
TYPE
: Specifies the type of provisioner to use. You must specify one of the following types:file
: Copies files or directories from the machine where Terraform is running to the new resource. When the file provisioner communicates with a Windows system over SSH, you must configure OpenSSH to run the commands withcmd.exe
and not PowerShell. PowerShell causes file parsing errors because it is incompatible with both Unix shells and the Windows command interpreter.local-exec
: Invokes an executable on the local machine after Terraform creates the resource.remote-exec
: Invokes an executable on the remote resource after Terraform creates the resource.
LABEL
: Optional attribute for adding a unique name. Refer to Resource naming for label recommendations.
The type of provisioner determines which arguments you can add to the block. All types can use the connection
argument. The following table lists each type's supported arguments:
Provisioner type | Arguments |
---|---|
file | source content destination |
local-exec | command working_dir interpreter environment when quiet |
remote-exec | inline script scripts |
All types | connection on_failure |
Summary
- Data type: Block.
- Default: None.
source
The source
specifies the location of a file or directory to copy to the location specified in the destination
argument.
resource {
provisioner "file" {
source = "<path>"
}
}
You can specify a string value that contains an expression. You can't use the source
argument and the content
argument in the same provisioner "file"
block.
When the source
argument specifies a directory and the type
argument in the provisioner connection settings is set to ssh
, the corresponding directory specified in the destination
argument must already exist. You can add a provisioner "remote-exec"
block to your resource
configuration to create the directory. If the directory does not already exist, Terraform creates it when the type
argument in the provisioner connection settings is set to winrm
.
Adding a trailing slash to the source
argument path instructs Terraform to copy the contents of the directory to the destination
directory. For example, when source = "/foo/"
and destination = "/temp"
, Terraform uploads the contents of /foo
directory into /tmp
.
Without a trailing slash, Terraform creates the directory under the directory specified in the destination
. For example, when source = "/foo"
and destination = "/temp"
, Terraform uploads the /foo
directory to /tmp/foo
.
Summary
- Data type: String.
- Default: None.
- Example: Copy content to new resources.
content
The content
argument specifies content to write directly to the location specified in the destination
argument.
resource {
provisioner "file" {
content = "<content>"
}
}
When destination
points to a file, Terraform writes the value of the content
argument to the file. When destination
points to a directory, Terraform creates a file named tf-file-content
inside the directory. We recommend setting the destination
argument to a file when using content
argument. Do not use the content
argument and the source
argument in the same provisioner "file"
block.
You can specify a string value that contains an expression. You can't use the source
argument and the content
argument in the same provisioner "file"
block.
Summary
- Data type: String.
- Default: None.
- Example: Copy content to new resources.
destination
The destination
argument specifies a path on the remote resource that Terraform copies content to. You can use either source
or content
argument to provide content to the destination
path.
resource {
provisioner "file" {
destination = "<path>"
}
}
The remote system, not Terraform, evaluates the path you provide in the destination
argument. As a result, valid values can vary depending on the operating system and remote access software running on the target.
When the type
argument in the provisioner connection settings is set to ssh
, the provisioner passes the destination path as-is to the scp
program on the remote host. By default, the OpenSSH scp
implementation runs in the remote user's home directory. As a result, you can specify a relative path to upload into the home directory or an absolute path to upload to a different location.
The remote scp
process runs with the access level of the user specified in the provisioner connection settings, so permissions may prevent Terraform from writing directly to locations outside of the home directory.
When the type
argument in the provisioner connection settings is set to winrm
, Terraform uses PowerShell to interpret the destination
path. As a result, you must not use meta-characters that PowerShell might interpret. You should specifically avoid including untrusted external input in your destination
argument because doing so can let arbitrary PowerShell code execute on the remote system.
Terraform performs the following process over WinRM connections:
- Generates a temporary filename in the directory set in the remote system's
TEMP
environment variable. - Generates a sequence of
echo
commands to gradually append base64-encoded chunks of the source file to the temporary file. - Uses an uploaded PowerShell script to read the temporary file, base64-decode, and write the raw result into the destination file.
Modern Windows systems support running an OpenSSH server, so we strongly recommend choosing SSH over WinRM.
Summary
- Data type: String.
- Default: None.
- Example: Copy content to new resources.
command
The command
argument specifies a command for a local executable to run. You can specify an absolute path or a relative path to the current working directory.
resource {
provisioner "local-exec" {
command = "<path>"
}
}
Terraform evaluates the command in a local shell and can use environment variables for variable substitution. We do not recommend using Terraform variables for variable substitution because doing so can lead to shell injection vulnerabilities. Instead, use the environment
parameter and environment variable substitution. Refer to the following OWASP article for more information about injection flaws: Code Injection.
Summary
- Data type: String.
- Default: None.
- This argument is required in the
provisioner "local-exec"
block. - Example: Invoke executables.
working_dir
The working_dir
block specifies the working directory where Terraform executes the command specified in the the command
argument. You can specify a relative path to the current working directory or an absolute path. The directory must already exist.
resource {
provisioner "local-exec" {
working_dir = "<path>"
}
}
Summary
- Data type: String.
- Default: None.
- Example: Invoke executables.
interpreter
The interpreter
block specifies a list of interpreter arguments for running the executable specified in the command
argument.
resource {
provisioner "local-exec" {
interpreter = [ "<path/to/interpreter>", "<command argument>" ]
}
}
The first argument in the list is a path to the interpreter. You can specify a relative path to the current working directory or an absolute path. If you do not specify an interpreter, Terraform uses operating system defaults.
Summary
- Data type: List.
- Default: None.
- Example: Invoke executables.
environment
The environment
block specifies a block of key value pairs that represent the environment for running the command specified in the command
argument.
resource {
provisioner "local-exec" {
environment {
<KEY> = <VALUE>
}
}
}
Summary
- Data type: Block.
- Default: None.
- Example: Invoke executables.
when
The when
argument specifies a Terraform command that triggers actions specified in the provisioner.
resource {
provisioner "local-exec" {
when = <Terraform command>
}
}
When you run the specified Terraform command, Terraform performs run the command specified in the command
argument. Refer to Destroy-time provisioners for instructions on using the when
argument.
Summary
- Data type: Terraform command.
- Default: None.
- Example: Invoke executables.
quiet
The quiet
argument disables printing the command
argument's output to stdout
.
resource {
provisioner "local-exec" {
quiet = <boolean>
}
}
When quiet
is set to true
, Terraform prints "Suppressed by quiet=true"
to stdout
. Terraform still prints the output of the command.
Summary
- Data type: Boolean.
- Default: None.
inline
Specifies a list of command strings to execute on the remote resource.
resource {
# ...
provisioner "remote-exec" {
inline = [ "<command>" ]
}
}
The provisioner uses the remote resource's default shell unless you specify a shell as the first command, for example #!/bin/bash
. You cannot add an inline
argument in the same provisioner with script
or scripts
.
Summary
- Data type: List.
- Default: None.
script
Specifies the relative or absolute path to a script on the local machine to copy and execute on the remote resource.
resource {
# ...
provisioner "remote-exec" {
scripts = "<path-to-script>"
}
}
You cannot add a script
argument in the same provisioner with inline
or scripts
.
Summary
- Data type: String.
- Default: None.
scripts
Specifies a list of relative or absolute paths to script files on the local machine to copy and execute on the remote resource.
resource {
# ...
provisioner "remote-exec" {
scripts = [ "<path-to-script>" ]
}
}
You cannot add a scripts
argument in the same provisioner with inline
or script
.
Summary
- Data type: List.
- Default: None.
Examples
The following examples show how to write configuration for common use cases.
Define an AWS instance
The following example defines an aws_instance
resource named web
.
resource "aws_instance" "web" {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
}
Create multiple instances of a resource
You can use either count
or the for_each
block to create multiple instances of a resource. The count
argument is most suitable for creating multiple instances that are identical or nearly identical. The for_each
argument is most suitable for creating multiple similar instances based on attributes defined in a map or set.
The following example creates one instance for each subnet provided in the input variable:
variable "subnet_ids" {
type = list(string)
}
resource "aws_instance" "server" {
count = length(var.subnet_ids)
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
subnet_id = var.subnet_ids[count.index]
tags = {
Name = "Server ${count.index}"
}
}
Specify a dependency
In the following example, the aws_iam_instance_profile
resource references the aws_iam_role
resource, instructing Terraform to create the upstream resource first. The aws_iam_role_policy
resource configures an IAM policy that lets the EC2 instance access the S3 API.
Terraform infers that it must create the instance profile before the EC2 instance, but it cannot infer that the software running in the EC2 instance needs access to the S3 API in order to boot properly. As a result, the configuration explicitly instructs Terraform to create the aws_iam_role_policy
first:
resource "aws_iam_role" "example" {
name = "example"
assume_role_policy = "..."
}
resource "aws_iam_instance_profile" "example" {
role = aws_iam_role.example.name
}
resource "aws_iam_role_policy" "example" {
name = "example"
role = aws_iam_role.example.name
policy = jsonencode({
"Statement" = [{
"Action" = "s3:*",
"Effect" = "Allow",
}],
})
}
resource "aws_instance" "example" {
ami = "data.aws_ami.example.id"
instance_type = "t2.micro"
iam_instance_profile = aws_iam_instance_profile.example
depends_on = [
aws_iam_role_policy.example
]
}
data "aws_ami" "example" {
# AMI configuration
}
Note that the aws_iam_role
resource is partially defined. Refer to the AWS provider documentation for all configuration settings.
Select an alternate provider configuration
In the following example, the google_compute_instance
resource selects the provider configuration with the europe
alias.
provider "google" {
region = "us-central1"
}
provider "google" {
alias = "europe"
region = "europe-west1"
}
resource "google_compute_instance" "example" {
provider = google.europe
# ...
}
Ignore attribute changes
In the following example, Terraform ignores changes to the resource's tags:
resource "aws_instance" "example" {
# ...
lifecycle {
ignore_changes = [tags]
}
}
Specify triggers that replace resources
In the following example, Terraform replaces aws_appautoscaling_target
each time this instance of aws_ecs_service
is replaced:
resource "aws_appautoscaling_target" "ecs_target" {
...
lifecycle {
replace_triggered_by = [
aws_ecs_service.svc.id
]
}
}
Apply custom conditions
The following example includes several configurations that illustrate how to define precondition
and postcondition
arguments in the lifecycle
meta-argument.
The following data
block instructs Terraform to retrieve the ID of the ami-abc123
AMI:
data "aws_ami" "example" {
owners = ["amazon"]
filter {
name = "image-id"
values = ["ami-abc123"]
}
}
In the following code, the precondition
block specifies that the AMI ID retrieved from the data
block must include x86_64
as its architecture
attribute. The postcondition
block specifies that the EC2 instance must be allocated a public DNS hostname. When either condition is not met, Terraform returns the error_message
for the failed condition:
resource "aws_instance" "example" {
instance_type = "t3.micro"
ami = data.aws_ami.example.id
lifecycle {
precondition {
condition = data.aws_ami.example.architecture == "x86_64"
error_message = "The selected AMI must be for the x86_64 architecture."
}
postcondition {
condition = self.public_dns != ""
error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled."
}
}
}
The following data
block retrieves the root storage volume connected to the aws_instance.example
EC2 instance using the volume_id
attribute. When a data
resource verifies the result of a managed resource declared in the same configuration, you must define the check in a postcondition
block in the resource so that Terraform waits for changes to the managed resource to complete before reading the data resource.
data "aws_ebs_volume" "example" {
filter {
name = "volume-id"
values = [aws_instance.example.root_block_device[0].volume_id]
}
lifecycle {
# The EC2 instance will have an encrypted root volume.
postcondition {
condition = self.encrypted
error_message = "The server's root volume is not encrypted."
}
}
}
output "api_base_url" {
value = "https://${aws_instance.example.private_dns}:8433/"
}
Copy content to new resources
The following examples use the file
provisioner type to copy artifacts from the machine where Terraform is running to the newly created resource.
resource "aws_instance" "web" {
# ...
# Copies the myapp.conf file to /etc/myapp.conf
provisioner "file" {
source = "conf/myapp.conf"
destination = "/etc/myapp.conf"
}
# Copies the string in content into /tmp/file.log
provisioner "file" {
content = "ami used: ${self.ami}"
destination = "/tmp/file.log"
}
# Copies the configs.d folder to /etc/configs.d
provisioner "file" {
source = "conf/configs.d"
destination = "/etc"
}
# Copies all files and folders in apps/app1 to D:/IIS/webapp1
provisioner "file" {
source = "apps/app1/"
destination = "D:/IIS/webapp1"
}
}
Invoke executables
You can configure provisioners to perform remote operations, such as executing scripts or running commands.
In the following example, Terraform connects to the web
instance using the connection
settings so that the remote-exec
provisioner can run the puppet apply
and consul join
commands on the resource:
resource "aws_instance" "web" {
# ...
connection {
type = "ssh"
user = "root"
password = var.root_password
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"puppet apply",
"consul join ${aws_instance.web.private_ip}",
]
}
}
In the following example, Terraform uploads a script to the instance and provides inline commands to run the script:
resource "aws_instance" "web" {
# ...
provisioner "file" {
source = "script.sh"
destination = "/tmp/script.sh"
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/script.sh",
"/tmp/script.sh args",
]
}
}
Connect to remote resources
The following example establishes a connection that all provisioners in the resource
block can use to run commands on the remote resource:
resource "aws_instance" "web" {
# ...
connection {
type = "ssh"
user = "root"
password = var.root_password
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"puppet apply",
"consul join ${aws_instance.web.private_ip}",
]
}
}
Define provisioner failure behaviors
In the following example, Terraform runs the echo
command on the local machine after creating the web
resource. Terraform continues with the operation if the command fails:
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
command = "echo The server's IP address is ${self.private_ip}"
on_failure = continue
}
}