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