1---
2layout: "language"
3page_title: "Input Variables - Configuration Language"
4sidebar_current: "docs-config-variables"
5description: |-
6  Input variables are parameters for Terraform modules.
7  This page covers configuration syntax for variables.
8---
9
10# Input Variables
11
12> **Hands-on:** Try the [Customize Terraform Configuration with Variables](https://learn.hashicorp.com/tutorials/terraform/variables?in=terraform/configuration-language&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
13
14Input variables serve as parameters for a Terraform module, allowing aspects
15of the module to be customized without altering the module's own source code,
16and allowing modules to be shared between different configurations.
17
18When you declare variables in the root module of your configuration, you can
19set their values using CLI options and environment variables.
20When you declare them in [child modules](/docs/language/modules/index.html),
21the calling module should pass values in the `module` block.
22
23If you're familiar with traditional programming languages, it can be useful to
24compare Terraform modules to function definitions:
25
26- Input variables are like function arguments.
27- [Output values](./outputs.html) are like function return values.
28- [Local values](./locals.html) are like a function's temporary local variables.
29
30-> **Note:** For brevity, input variables are often referred to as just
31"variables" or "Terraform variables" when it is clear from context what sort of
32variable is being discussed. Other kinds of variables in Terraform include
33_environment variables_ (set by the shell where Terraform runs) and _expression
34variables_ (used to indirectly represent a value in an
35[expression](/docs/language/expressions/index.html)).
36
37## Declaring an Input Variable
38
39Each input variable accepted by a module must be declared using a `variable`
40block:
41
42```hcl
43variable "image_id" {
44  type = string
45}
46
47variable "availability_zone_names" {
48  type    = list(string)
49  default = ["us-west-1a"]
50}
51
52variable "docker_ports" {
53  type = list(object({
54    internal = number
55    external = number
56    protocol = string
57  }))
58  default = [
59    {
60      internal = 8300
61      external = 8300
62      protocol = "tcp"
63    }
64  ]
65}
66```
67
68The label after the `variable` keyword is a name for the variable, which must
69be unique among all variables in the same module. This name is used to
70assign a value to the variable from outside and to reference the variable's
71value from within the module.
72
73The name of a variable can be any valid [identifier](/docs/language/syntax/configuration.html#identifiers)
74_except_ the following: `source`, `version`, `providers`, `count`, `for_each`, `lifecycle`, `depends_on`, `locals`.
75
76These names are reserved for meta-arguments in
77[module configuration blocks](/docs/language/modules/syntax.html), and cannot be
78declared as variable names.
79
80## Arguments
81
82Terraform CLI defines the following optional arguments for variable declarations:
83
84- [`default`][inpage-default] - A default value which then makes the variable optional.
85- [`type`][inpage-type] - This argument specifies what value types are accepted for the variable.
86- [`description`][inpage-description] - This specifies the input variable's documentation.
87- [`validation`][inpage-validation] - A block to define validation rules, usually in addition to type constraints.
88- [`sensitive`][inpage-sensitive] - Limits Terraform UI output when the variable is used in configuration.
89
90### Default values
91
92[inpage-default]: #default-values
93
94The variable declaration can also include a `default` argument. If present,
95the variable is considered to be _optional_ and the default value will be used
96if no value is set when calling the module or running Terraform. The `default`
97argument requires a literal value and cannot reference other objects in the
98configuration.
99
100### Type Constraints
101
102[inpage-type]: #type-constraints
103
104The `type` argument in a `variable` block allows you to restrict the
105[type of value](/docs/language/expressions/types.html) that will be accepted as
106the value for a variable. If no type constraint is set then a value of any type
107is accepted.
108
109While type constraints are optional, we recommend specifying them; they
110can serve as helpful reminders for users of the module, and they
111allow Terraform to return a helpful error message if the wrong type is used.
112
113Type constraints are created from a mixture of type keywords and type
114constructors. The supported type keywords are:
115
116* `string`
117* `number`
118* `bool`
119
120The type constructors allow you to specify complex types such as
121collections:
122
123* `list(<TYPE>)`
124* `set(<TYPE>)`
125* `map(<TYPE>)`
126* `object({<ATTR NAME> = <TYPE>, ... })`
127* `tuple([<TYPE>, ...])`
128
129The keyword `any` may be used to indicate that any type is acceptable. For
130more information on the meaning and behavior of these different types, as well
131as detailed information about automatic conversion of complex types, see
132[Type Constraints](/docs/language/expressions/types.html).
133
134If both the `type` and `default` arguments are specified, the given default
135value must be convertible to the specified type.
136
137### Input Variable Documentation
138
139[inpage-description]: #input-variable-documentation
140
141Because the input variables of a module are part of its user interface, you can
142briefly describe the purpose of each variable using the optional
143`description` argument:
144
145```hcl
146variable "image_id" {
147  type        = string
148  description = "The id of the machine image (AMI) to use for the server."
149}
150```
151
152The description should concisely explain the purpose
153of the variable and what kind of value is expected. This description string
154might be included in documentation about the module, and so it should be written
155from the perspective of the user of the module rather than its maintainer. For
156commentary for module maintainers, use comments.
157
158### Custom Validation Rules
159
160[inpage-validation]: #custom-validation-rules
161
162-> This feature was introduced in Terraform CLI v0.13.0.
163
164In addition to Type Constraints as described above, a module author can specify
165arbitrary custom validation rules for a particular variable using a `validation`
166block nested within the corresponding `variable` block:
167
168```hcl
169variable "image_id" {
170  type        = string
171  description = "The id of the machine image (AMI) to use for the server."
172
173  validation {
174    condition     = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
175    error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
176  }
177}
178```
179
180The `condition` argument is an expression that must use the value of the
181variable to return `true` if the value is valid, or `false` if it is invalid.
182The expression can refer only to the variable that the condition applies to,
183and _must not_ produce errors.
184
185If the failure of an expression is the basis of the validation decision, use
186[the `can` function](/docs/language/functions/can.html) to detect such errors. For example:
187
188```hcl
189variable "image_id" {
190  type        = string
191  description = "The id of the machine image (AMI) to use for the server."
192
193  validation {
194    # regex(...) fails if it cannot find a match
195    condition     = can(regex("^ami-", var.image_id))
196    error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
197  }
198}
199```
200
201If `condition` evaluates to `false`, Terraform will produce an error message
202that includes the sentences given in `error_message`. The error message string
203should be at least one full sentence explaining the constraint that failed,
204using a sentence structure similar to the above examples.
205
206### Suppressing Values in CLI Output
207
208[inpage-sensitive]: #suppressing-values-in-cli-output
209
210-> This feature was introduced in Terraform v0.14.0.
211
212> **Hands-on:** Try the [Protect Sensitive Input Variables](https://learn.hashicorp.com/tutorials/terraform/sensitive-variables?in=terraform/configuration-language&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
213
214Setting a variable as `sensitive` prevents Terraform from showing its value in
215the `plan` or `apply` output, when you use that variable elsewhere in your
216configuration.
217
218Terraform will still record sensitive values in the [state](/docs/language/state/index.html),
219and so anyone who can access the state data will have access to the sensitive
220values in cleartext. For more information, see
221[_Sensitive Data in State_](/docs/language/state/sensitive-data.html).
222
223Declare a variable as sensitive by setting the `sensitive` argument to `true`:
224
225```
226variable "user_information" {
227  type = object({
228    name    = string
229    address = string
230  })
231  sensitive = true
232}
233
234resource "some_resource" "a" {
235  name    = var.user_information.name
236  address = var.user_information.address
237}
238```
239
240Any expressions whose result depends on the sensitive variable will be treated
241as sensitive themselves, and so in the above example the two arguments of
242`resource "some_resource" "a"` will also be hidden in the plan output:
243
244```
245Terraform will perform the following actions:
246
247  # some_resource.a will be created
248  + resource "some_resource" "a" {
249      + name    = (sensitive)
250      + address = (sensitive)
251    }
252
253Plan: 1 to add, 0 to change, 0 to destroy.
254```
255
256In some cases where you use a sensitive variable inside a nested block, Terraform
257may treat the entire block as redacted. This happens for resource types where
258all of the blocks of a particular type are required to be unique, and so
259disclosing the content of one block might imply the content of a sibling block.
260
261```
262  # some_resource.a will be updated in-place
263  ~ resource "some_resource" "a" {
264      ~ nested_block {
265          # At least one attribute in this block is (or was) sensitive,
266          # so its contents will not be displayed.
267        }
268    }
269```
270
271A provider can also
272[declare an attribute as sensitive](/docs/extend/best-practices/sensitive-state.html#using-the-sensitive-flag),
273which will cause Terraform to hide it from regular output regardless of how
274you assign it a value. For more information, see
275[Sensitive Resource Attributes](/docs/language/expressions/references.html#sensitive-resource-attributes).
276
277If you use a sensitive value from as part of an
278[output value](/docs/language/values/outputs.html) then Terraform will require
279you to also mark the output value itself as sensitive, to confirm that you
280intended to export it.
281
282#### Cases where Terraform may disclose a sensitive variable
283
284A `sensitive` variable is a configuration-centered concept, and values are sent to providers without any obfuscation. A provider error could disclose a value if that value is included in the error message. For example, a provider might return the following error even if "foo" is a sensitive value: `"Invalid value 'foo' for field"`
285
286If a resource attribute is used as, or part of, the provider-defined resource id, an `apply` will disclose the value. In the example below, the `prefix` attribute has been set to a sensitive variable, but then that value ("jae") is later disclosed as part of the resource id:
287
288```
289  # random_pet.animal will be created
290  + resource "random_pet" "animal" {
291      + id        = (known after apply)
292      + length    = 2
293      + prefix    = (sensitive)
294      + separator = "-"
295    }
296
297Plan: 1 to add, 0 to change, 0 to destroy.
298
299...
300
301random_pet.animal: Creating...
302random_pet.animal: Creation complete after 0s [id=jae-known-mongoose]
303```
304
305## Using Input Variable Values
306
307Within the module that declared a variable, its value can be accessed from
308within [expressions](/docs/language/expressions/index.html) as `var.<NAME>`,
309where `<NAME>` matches the label given in the declaration block:
310
311-> **Note:** Input variables are _created_ by a `variable` block, but you
312_reference_ them as attributes on an object named `var`.
313
314```hcl
315resource "aws_instance" "example" {
316  instance_type = "t2.micro"
317  ami           = var.image_id
318}
319```
320
321The value assigned to a variable can only be accessed in expressions within
322the module where it was declared.
323
324## Assigning Values to Root Module Variables
325
326When variables are declared in the root module of your configuration, they
327can be set in a number of ways:
328
329* [In a Terraform Cloud workspace](/docs/cloud/workspaces/variables.html).
330* Individually, with the `-var` command line option.
331* In variable definitions (`.tfvars`) files, either specified on the command line
332  or automatically loaded.
333* As environment variables.
334
335The following sections describe these options in more detail. This section does
336not apply to _child_ modules, where values for input variables are instead
337assigned in the configuration of their parent module, as described in
338[_Modules_](/docs/language/modules/index.html).
339
340### Variables on the Command Line
341
342To specify individual variables on the command line, use the `-var` option
343when running the `terraform plan` and `terraform apply` commands:
344
345```
346terraform apply -var="image_id=ami-abc123"
347terraform apply -var='image_id_list=["ami-abc123","ami-def456"]' -var="instance_type=t2.micro"
348terraform apply -var='image_id_map={"us-east-1":"ami-abc123","us-east-2":"ami-def456"}'
349```
350
351The above examples show appropriate syntax for Unix-style shells, such as on
352Linux or macOS. For more information on shell quoting, including additional
353examples for Windows Command Prompt, see
354[Input Variables on the Command Line](/docs/cli/commands/plan.html#input-variables-on-the-command-line).
355
356You can use the `-var` option multiple times in a single command to set several
357different variables.
358
359<a id="variable-files"></a>
360
361### Variable Definitions (`.tfvars`) Files
362
363To set lots of variables, it is more convenient to specify their values in
364a _variable definitions file_ (with a filename ending in either `.tfvars`
365or `.tfvars.json`) and then specify that file on the command line with
366`-var-file`:
367
368```
369terraform apply -var-file="testing.tfvars"
370```
371
372-> **Note:** This is how Terraform Cloud passes
373[workspace variables](/docs/cloud/workspaces/variables.html) to Terraform.
374
375A variable definitions file uses the same basic syntax as Terraform language
376files, but consists only of variable name assignments:
377
378```hcl
379image_id = "ami-abc123"
380availability_zone_names = [
381  "us-east-1a",
382  "us-west-1c",
383]
384```
385
386Terraform also automatically loads a number of variable definitions files
387if they are present:
388
389* Files named exactly `terraform.tfvars` or `terraform.tfvars.json`.
390* Any files with names ending in `.auto.tfvars` or `.auto.tfvars.json`.
391
392Files whose names end with `.json` are parsed instead as JSON objects, with
393the root object properties corresponding to variable names:
394
395```json
396{
397  "image_id": "ami-abc123",
398  "availability_zone_names": ["us-west-1a", "us-west-1c"]
399}
400```
401
402### Environment Variables
403
404As a fallback for the other ways of defining variables, Terraform searches
405the environment of its own process for environment variables named `TF_VAR_`
406followed by the name of a declared variable.
407
408This can be useful when running Terraform in automation, or when running a
409sequence of Terraform commands in succession with the same variables.
410For example, at a `bash` prompt on a Unix system:
411
412```
413$ export TF_VAR_image_id=ami-abc123
414$ terraform plan
415...
416```
417
418On operating systems where environment variable names are case-sensitive,
419Terraform matches the variable name exactly as given in configuration, and
420so the required environment variable name will usually have a mix of upper
421and lower case letters as in the above example.
422
423### Complex-typed Values
424
425When variable values are provided in a variable definitions file, you can use
426Terraform's usual syntax for
427[literal expressions](/docs/language/expressions/types.html#literal-expressions)
428to assign complex-typed values, like lists and maps.
429
430Some special rules apply to the `-var` command line option and to environment
431variables. For convenience, Terraform defaults to interpreting `-var` and
432environment variable values as literal strings, which need only shell quoting,
433and no special quoting for Terraform. For example, in a Unix-style shell:
434
435```
436$ export TF_VAR_image_id='ami-abc123'
437```
438
439However, if a root module variable uses a [type constraint](#type-constraints)
440to require a complex value (list, set, map, object, or tuple), Terraform will
441instead attempt to parse its value using the same syntax used within variable
442definitions files, which requires careful attention to the string escaping rules
443in your shell:
444
445```
446$ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]'
447```
448
449For readability, and to avoid the need to worry about shell escaping, we
450recommend always setting complex variable values via variable definitions files.
451For more information on quoting and escaping for `-var` arguments,
452see
453[Input Variables on the Command Line](/docs/cli/commands/plan.html#input-variables-on-the-command-line).
454
455### Values for Undeclared Variables
456
457If you have defined a variable value, but not its corresponding `variable {}`
458definition, you may get an error or warning depending on how you have provided
459that value.
460
461If you provide values for undeclared variables defined as [environment variables](#environment-variables)
462you will not get an error or warning. This is because environment variables may
463be declared but not used in all configurations that might be run.
464
465If you provide values for undeclared variables defined [in a file](#variable-definitions-tfvars-files)
466you will get a warning. This is to help in cases where you have provided a variable
467value _meant_ for a variable declaration, but perhaps there is a mistake in the
468value definition. For example, the following configuration:
469
470```terraform
471variable "moose" {
472  type = string
473}
474```
475
476And the following `.tfvars` file:
477
478```hcl
479mosse = "Moose"
480```
481
482Will cause Terraform to warn you that there is no variable declared `"mosse"`, which can help
483you spot this mistake.
484
485If you use `.tfvars` files across multiple configurations and expect to continue to see this warning,
486you can use the [`-compact-warnings`](https://www.terraform.io/docs/cli/commands/plan.html#compact-warnings)
487option to simplify your output.
488
489If you provide values for undeclared variables on the [command line](#variables-on-the-command-line),
490Terraform will error. To avoid this error, either declare a variable block for the value, or remove
491the variable value from your Terraform call.
492
493### Variable Definition Precedence
494
495The above mechanisms for setting variables can be used together in any
496combination. If the same variable is assigned multiple values, Terraform uses
497the _last_ value it finds, overriding any previous values. Note that the same
498variable cannot be assigned multiple values within a single source.
499
500Terraform loads variables in the following order, with later sources taking
501precedence over earlier ones:
502
503* Environment variables
504* The `terraform.tfvars` file, if present.
505* The `terraform.tfvars.json` file, if present.
506* Any `*.auto.tfvars` or `*.auto.tfvars.json` files, processed in lexical order
507  of their filenames.
508* Any `-var` and `-var-file` options on the command line, in the order they
509  are provided. (This includes variables set by a Terraform Cloud
510  workspace.)
511
512~> **Important:** In Terraform 0.12 and later, variables with map and object
513values behave the same way as other variables: the last value found overrides
514the previous values. This is a change from previous versions of Terraform, which
515would _merge_ map values instead of overriding them.
516