| --- | |
| description: >- | |
| Input variables allow you to customize modules without altering their source | |
| code. Learn how to declare, define, and reference variables in configurations. | |
| --- | |
| # Input Variables | |
| Input variables let you customize aspects of modules without altering | |
| the module's own source code. This functionality allows you to share modules across different | |
| OpenTofu configurations, making your module composable and reusable. | |
| When you declare variables in the root module of your configuration, you can | |
| set their values using CLI options and environment variables. | |
| When you declare them in [child modules](../../language/modules/index.mdx), | |
| the calling module should pass values in the `module` block. | |
| If you're familiar with traditional programming languages, it can be useful to | |
| compare modules to function definitions: | |
| * Input variables are like function arguments. | |
| * [Output values](../../language/values/outputs.mdx) are like function return values. | |
| * [Local values](../../language/values/locals.mdx) are like a function's temporary local variables. | |
| :::note | |
| For brevity, input variables are often referred to as just | |
| "variables" or "OpenTofu variables" when it is clear from context what sort of | |
| variable is being discussed. Other kinds of variables in OpenTofu include | |
| _environment variables_ (set by the shell where OpenTofu runs) and _expression | |
| variables_ (used to indirectly represent a value in an | |
| [expression](../../language/expressions/index.mdx)). | |
| ::: | |
| ## Declaring an Input Variable | |
| Each input variable accepted by a module must be declared using a `variable` | |
| block: | |
| ```hcl | |
| variable "image_id" { | |
| type = string | |
| } | |
| variable "availability_zone_names" { | |
| type = list(string) | |
| default = ["us-west-1a"] | |
| } | |
| variable "docker_ports" { | |
| type = list(object({ | |
| internal = number | |
| external = number | |
| protocol = string | |
| })) | |
| default = [ | |
| { | |
| internal = 8300 | |
| external = 8300 | |
| protocol = "tcp" | |
| } | |
| ] | |
| } | |
| ``` | |
| The label after the `variable` keyword is a name for the variable, which must | |
| be unique among all variables in the same module. This name is used to | |
| assign a value to the variable from outside and to reference the variable's | |
| value from within the module. | |
| The name of a variable can be any valid [identifier](../../language/syntax/configuration.mdx#identifiers) | |
| _except_ the following: `source`, `version`, `providers`, `count`, `for_each`, `lifecycle`, `depends_on`, `locals`. | |
| These names are reserved for meta-arguments in | |
| [module configuration blocks](../../language/modules/syntax.mdx), and cannot be | |
| declared as variable names. | |
| ## Arguments | |
| OpenTofu CLI defines the following optional arguments for variable declarations: | |
| * [`default`][inpage-default] - A default value which then makes the variable optional. | |
| * [`type`][inpage-type] - This argument specifies what value types are accepted for the variable. | |
| * [`description`][inpage-description] - This specifies the input variable's documentation. | |
| * [`validation`][inpage-validation] - A block to define validation rules, usually in addition to type constraints. | |
| * [`sensitive`][inpage-sensitive] - Limits OpenTofu UI output when the variable is used in configuration. | |
| * [`ephemeral`][inpage-ephemeral] - Limits the usage of the variable to ephemeral contexts. | |
| * [`nullable`][inpage-nullable] - Specify if the variable can be `null` within the module. | |
| * [`deprecated`][inpage-deprecated] - Mark the variable as deprecated to warn callers about migration. | |
| * [`const`][inpage-const] - Value must be constant (evaluated without state). | |
| ### Default values | |
| [inpage-default]: #default-values | |
| The variable declaration can also include a `default` argument. If present, | |
| the variable is considered to be _optional_ and the default value will be used | |
| if no value is set when calling the module or running OpenTofu. The `default` | |
| argument requires a literal value and cannot reference other objects in the | |
| configuration. | |
| ### Type Constraints | |
| [inpage-type]: #type-constraints | |
| The `type` argument in a `variable` block allows you to restrict the | |
| [type of value](../../language/expressions/types.mdx) that will be accepted as | |
| the value for a variable. If no type constraint is set then a value of any type | |
| is accepted. | |
| While type constraints are optional, we recommend specifying them; they | |
| can serve as helpful reminders for users of the module, and they | |
| allow OpenTofu to return a helpful error message if the wrong type is used. | |
| Type constraints are created from a mixture of type keywords and type | |
| constructors. The supported type keywords are: | |
| * `string` | |
| * `number` | |
| * `bool` | |
| The type constructors allow you to specify complex types such as | |
| collections: | |
| * `list(<TYPE>)` | |
| * `set(<TYPE>)` | |
| * `map(<TYPE>)` | |
| * `object({<ATTR NAME> = <TYPE>, ... })` | |
| * `tuple([<TYPE>, ...])` | |
| The keyword `any` may be used to indicate that any type is acceptable. For | |
| more information on the meaning and behavior of these different types, as well | |
| as detailed information about automatic conversion of complex types, see | |
| [Type Constraints](../../language/expressions/types.mdx). | |
| If both the `type` and `default` arguments are specified, the given default | |
| value must be convertible to the specified type. | |
| ### Input Variable Documentation | |
| [inpage-description]: #input-variable-documentation | |
| Because the input variables of a module are part of its user interface, you can | |
| briefly describe the purpose of each variable using the optional | |
| `description` argument: | |
| ```hcl | |
| variable "image_id" { | |
| type = string | |
| description = "The id of the machine image (AMI) to use for the server." | |
| } | |
| ``` | |
| The description should concisely explain the purpose | |
| of the variable and what kind of value is expected. This description string | |
| might be included in documentation about the module, and so it should be written | |
| from the perspective of the user of the module rather than its maintainer. For | |
| commentary for module maintainers, use comments. | |
| ### Custom Validation Rules | |
| [inpage-validation]: #custom-validation-rules | |
| You can specify custom validation rules for a particular variable by adding a `validation` block within the corresponding `variable` block. The example below checks whether the AMI ID has the correct syntax. | |
| ```hcl | |
| variable "image_id" { | |
| type = string | |
| description = "The id of the machine image (AMI) to use for the server." | |
| validation { | |
| condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-" | |
| error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"." | |
| } | |
| } | |
| ``` | |
| Refer to [Custom Condition Checks](../../language/expressions/custom-conditions.mdx#input-variable-validation) for more details. | |
| ### Suppressing Values in CLI Output | |
| [inpage-sensitive]: #suppressing-values-in-cli-output | |
| Setting a variable as `sensitive` prevents OpenTofu from showing its value in | |
| the `plan` or `apply` output, when you use that variable elsewhere in your | |
| configuration. | |
| OpenTofu will still record sensitive values in the [state](../../language/state/index.mdx), | |
| and so anyone who can access the state data will have access to the sensitive | |
| values in cleartext. For more information, see | |
| [_Sensitive Data in State_](../../language/state/sensitive-data.mdx). | |
| Declare a variable as sensitive by setting the `sensitive` argument to `true`: | |
| ```hcl | |
| variable "user_information" { | |
| type = object({ | |
| name = string | |
| address = string | |
| }) | |
| sensitive = true | |
| } | |
| resource "some_resource" "a" { | |
| name = var.user_information.name | |
| address = var.user_information.address | |
| } | |
| ``` | |
| Any expressions whose result depends on the sensitive variable will be treated | |
| as sensitive themselves, and so in the above example the two arguments of | |
| `resource "some_resource" "a"` will also be hidden in the plan output: | |
| ``` | |
| OpenTofu will perform the following actions: | |
| # some_resource.a will be created | |
| + resource "some_resource" "a" { | |
| + name = (sensitive value) | |
| + address = (sensitive value) | |
| } | |
| Plan: 1 to add, 0 to change, 0 to destroy. | |
| ``` | |
| In some cases where you use a sensitive variable inside a nested block, OpenTofu | |
| may treat the entire block as redacted. This happens for resource types where | |
| all of the blocks of a particular type are required to be unique, and so | |
| disclosing the content of one block might imply the content of a sibling block. | |
| ``` | |
| # some_resource.a will be updated in-place | |
| ~ resource "some_resource" "a" { | |
| ~ nested_block { | |
| # At least one attribute in this block is (or was) sensitive, | |
| # so its contents will not be displayed. | |
| } | |
| } | |
| ``` | |
| A provider can also | |
| [declare an attribute as sensitive](https://developer.hashicorp.com/terraform/plugin/best-practices/sensitive-state#using-sensitive-flag-functionality), | |
| which will cause OpenTofu to hide it from regular output regardless of how | |
| you assign it a value. For more information, see | |
| [Sensitive Resource Attributes](../../language/expressions/references.mdx#sensitive-resource-attributes). | |
| If you use a sensitive value as part of an | |
| [output value](../../language/values/outputs.mdx) then OpenTofu will require | |
| you to also mark the output value itself as sensitive, to confirm that you | |
| intended to export it. | |
| #### Cases where OpenTofu may disclose a sensitive variable | |
| A `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"` | |
| If 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: | |
| ``` | |
| # random_pet.animal will be created | |
| + resource "random_pet" "animal" { | |
| + id = (known after apply) | |
| + length = 2 | |
| + prefix = (sensitive value) | |
| + separator = "-" | |
| } | |
| Plan: 1 to add, 0 to change, 0 to destroy. | |
| ... | |
| random_pet.animal: Creating... | |
| random_pet.animal: Creation complete after 0s [id=jae-known-mongoose] | |
| ``` | |
| ### Ephemerality | |
| [inpage-ephemeral]: #ephemeral-variables | |
| Setting a variable as `ephemeral` restricts its usage to the following ephemeral contexts: | |
| * [Ephemeral Resources](../ephemerality/ephemeral-resources.mdx) | |
| * [Ephemeral Variables](../values/variables.mdx#ephemerality) | |
| * [Ephemeral Outputs](../values/outputs.mdx#ephemerality) | |
| * [Locals](../values/locals.mdx#ephemerality) | |
| * [Providers](../providers/configuration.mdx) | |
| * [Provisioners](../resources/provisioners/syntax.mdx#suppressing-provisioner-logs-in-cli-output) | |
| * [Resource `connection` blocks](../resources/provisioners/connection.mdx#ephemeral-usage) | |
| * [Resource `write-only` attributes](../ephemerality/write-only-attributes.mdx) | |
| OpenTofu will not store ephemeral variable values in the [state](../../language/state/index.mdx) at all. | |
| Only the variable names will be saved in the plan for further processing during apply. | |
| Declare a variable as ephemeral by setting the `ephemeral` argument to `true`: | |
| ```hcl | |
| variable "user_password" { | |
| type = string | |
| ephemeral = true | |
| } | |
| ``` | |
| Any expressions whose result depends on the ephemeral variable will be treated | |
| as ephemeral themselves. | |
| ```hcl | |
| locals { | |
| sanitized = trimspace(var.user_password) # `sanitized` is an ephemeral local now | |
| } | |
| ``` | |
| If you use an ephemeral value as part of an | |
| [output value](../../language/values/outputs.mdx) then OpenTofu will require | |
| you to also configure the output block as ephemeral too. | |
| :::note | |
| Ephemeral variables on root modules require careful handling around `-var`/`-var-file`. Please refer to [`tofu apply` docs](../../cli/commands/apply.mdx#ephemeral-variables) | |
| ::: | |
| ### Disallowing Null Input Values | |
| [inpage-nullable]: #disallowing-null-input-values | |
| The `nullable` argument in a variable block controls whether the module caller | |
| may assign the value `null` to the variable. | |
| ```hcl | |
| variable "example" { | |
| type = string | |
| nullable = false | |
| } | |
| ``` | |
| The default value for `nullable` is `true`. When `nullable` is `true`, `null` | |
| is a valid value for the variable, and the module configuration must always | |
| account for the possibility of the variable value being `null`. Passing a | |
| `null` value as a module input argument will override any `default` value. | |
| Setting `nullable` to `false` ensures that the variable value will never be | |
| `null` within the module. If `nullable` is `false` and the variable has a | |
| `default` value, then OpenTofu uses the default when a module input argument is `null`. | |
| The `nullable` argument only controls where the direct value of the variable may be `null`. | |
| For variables of collection or structural types, such as lists or objects, | |
| the caller may still use `null` in nested elements or attributes, as long as | |
| the collection or structure itself is not null. | |
| ### Marking variable as deprecated | |
| [inpage-deprecated]: #marking-variable-as-deprecated | |
| The `deprecated` argument in a variable block indicates its deprecation and potential | |
| removal in the future. This attribute should contain a non-empty string and should provide | |
| instructions on how to migrate away from usage of this variable. Here is an example of the | |
| configuration: | |
| ```hcl | |
| variable "examle" { | |
| type = string | |
| deprecated = "'examle' variable must no longer be used due to a typo, use 'example' instead" | |
| } | |
| ``` | |
| The caller of the module will receive a warning if the deprecated variable is used in | |
| their configuration: | |
| ``` | |
| │ Warning: Variable marked as deprecated by the module author | |
| │ | |
| │ on main.tf line 3, in module "mod": | |
| │ 3: examle = "a" | |
| │ | |
| │ Variable "examle" is marked as deprecated with the following message: | |
| │ 'examle' variable must no longer be used due to a typo, use 'example' instead | |
| ``` | |
| Deprecation warnings can be filtered or disabled by using the `-deprecation` CLI | |
| argument. By default, deprecated module variables will be consolidated by using their variable | |
| name and the deprecation message. If two different modules are using a submodule with | |
| a deprecated variable, they will be shown together. In order to see them individually, | |
| `-consolidation-warnings=false` can be used. For more details, check its description | |
| in the command options for [plan](../../cli/commands/plan.mdx#other-options) and | |
| [apply](../../cli/commands/apply.mdx#apply-options). | |
| ### Marking variable as constant | |
| [inpage-const]: #marking-variable-as-const | |
| The `const = true` argument in a variable block indicates that it's value must be computed | |
| without access to state. This also ensures that it is able to be used as a constant value during evaluation | |
| of [module sources](../../language/modules/sources.mdx#support-for-variable-and-local-evaluation) and | |
| [backends](../../language/settings/backends/configuration.mdx). | |
| The inverse `const = false` prevents a variable from being used in any of the above evaluation context and | |
| explicitly declares it "not constant", regardless of the value or expression provided. | |
| If unspecified, OpenTofu inspects the configuration to determine if the expression or value provided for a variable | |
| may be used as a constant. | |
| ```hcl | |
| variable "dependency_version" { | |
| type = string | |
| const = true | |
| } | |
| module "my_mod" { | |
| source = "my-module-source" | |
| version = var.dependency_version | |
| } | |
| ``` | |
| ## Using Input Variable Values | |
| Within the module that declared a variable, its value can be accessed from | |
| within [expressions](../../language/expressions/index.mdx) as `var.<NAME>`, | |
| where `<NAME>` matches the label given in the declaration block: | |
| :::note | |
| Input variables are _created_ by a `variable` block, but you | |
| _reference_ them as attributes on an object named `var`. | |
| ::: | |
| ```hcl | |
| resource "aws_instance" "example" { | |
| instance_type = "t2.micro" | |
| ami = var.image_id | |
| } | |
| ``` | |
| The value assigned to a variable can only be accessed in expressions within | |
| the module where it was declared. | |
| ## Assigning Values to Root Module Variables | |
| When variables are declared in the root module of your configuration, they | |
| can be set in a number of ways: | |
| * Individually, with the `-var` command line option. | |
| * In variable definitions (`.tfvars`) files, either specified on the command line | |
| or automatically loaded. | |
| * As environment variables. | |
| The following sections describe these options in more detail. This section does | |
| not apply to _child_ modules, where values for input variables are instead | |
| assigned in the configuration of their parent module, as described in | |
| [_Modules_](../../language/modules/index.mdx). | |
| ### Variables on the Command Line | |
| To specify individual variables on the command line, use the `-var` option | |
| when running the `tofu plan` and `tofu apply` commands: | |
| ``` | |
| tofu apply -var="image_id=ami-abc123" | |
| tofu apply -var='image_id_list=["ami-abc123","ami-def456"]' -var="instance_type=t2.micro" | |
| tofu apply -var='image_id_map={"us-east-1":"ami-abc123","us-east-2":"ami-def456"}' | |
| ``` | |
| The above examples show appropriate syntax for Unix-style shells, such as on | |
| Linux or macOS. For more information on shell quoting, including additional | |
| examples for Windows Command Prompt, see | |
| [Input Variables on the Command Line](../../cli/commands/plan.mdx#input-variables-on-the-command-line). | |
| You can use the `-var` option multiple times in a single command to set several | |
| different variables. | |
| <a id="variable-files"></a> | |
| ### Variable Definitions (`.tfvars`) Files | |
| To set lots of variables, it is more convenient to specify their values in | |
| a _variable definitions file_ (with a filename ending in either `.tfvars` | |
| or `.tfvars.json`) and then specify that file on the command line with | |
| `-var-file`: | |
| ``` | |
| tofu apply -var-file="testing.tfvars" | |
| ``` | |
| A variable definitions file uses the same basic syntax as OpenTofu language | |
| files, but consists only of variable name assignments: | |
| ```hcl | |
| image_id = "ami-abc123" | |
| availability_zone_names = [ | |
| "us-east-1a", | |
| "us-west-1c", | |
| ] | |
| ``` | |
| OpenTofu also automatically loads a number of variable definitions files | |
| if they are present: | |
| * Files named exactly `terraform.tfvars` or `terraform.tfvars.json`. | |
| * Any files with names ending in `.auto.tfvars` or `.auto.tfvars.json`. | |
| Files whose names end with `.json` are parsed instead as JSON objects, with | |
| the root object properties corresponding to variable names: | |
| ```json | |
| { | |
| "image_id": "ami-abc123", | |
| "availability_zone_names": ["us-west-1a", "us-west-1c"] | |
| } | |
| ``` | |
| ### Environment Variables | |
| As a fallback for the other ways of defining variables, OpenTofu searches | |
| the environment of its own process for environment variables named `TF_VAR_` | |
| followed by the name of a declared variable. | |
| This can be useful when running OpenTofu in automation, or when running a | |
| sequence of OpenTofu commands in succession with the same variables. | |
| For example, at a `bash` prompt on a Unix system: | |
| ``` | |
| $ export TF_VAR_image_id=ami-abc123 | |
| $ tofu plan | |
| ... | |
| ``` | |
| On operating systems where environment variable names are case-sensitive, | |
| OpenTofu matches the variable name exactly as given in configuration, and | |
| so the required environment variable name will usually have a mix of upper | |
| and lower case letters as in the above example. | |
| ### Complex-typed Values | |
| When variable values are provided in a variable definitions file, you can use | |
| OpenTofu's usual syntax for | |
| [literal expressions](../../language/expressions/types.mdx#literal-expressions) | |
| to assign complex-typed values, like lists and maps. | |
| Some special rules apply to the `-var` command line option and to environment | |
| variables. For convenience, OpenTofu defaults to interpreting `-var` and | |
| environment variable values as literal strings, which need only shell quoting, | |
| and no special quoting for OpenTofu. For example, in a Unix-style shell: | |
| ``` | |
| $ export TF_VAR_image_id='ami-abc123' | |
| ``` | |
| However, if a root module variable uses a [type constraint](#type-constraints) | |
| to require a complex value (list, set, map, object, or tuple), OpenTofu will | |
| instead attempt to parse its value using the same syntax used within variable | |
| definitions files, which requires careful attention to the string escaping rules | |
| in your shell: | |
| ``` | |
| $ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]' | |
| ``` | |
| For readability, and to avoid the need to worry about shell escaping, we | |
| recommend always setting complex variable values via variable definitions files. | |
| For more information on quoting and escaping for `-var` arguments, | |
| see | |
| [Input Variables on the Command Line](../../cli/commands/plan.mdx#input-variables-on-the-command-line). | |
| ### Values for Undeclared Variables | |
| If you have defined a variable value, but not its corresponding `variable {}` | |
| definition, you may get an error or warning depending on how you have provided | |
| that value. | |
| If you provide values for undeclared variables defined as [environment variables](#environment-variables) | |
| you will not get an error or warning. This is because environment variables may | |
| be declared but not used in all configurations that might be run. | |
| If you provide values for undeclared variables defined [in a file](#variable-definitions-tfvars-files) | |
| you will get a warning. This is to help in cases where you have provided a variable | |
| value _meant_ for a variable declaration, but perhaps there is a mistake in the | |
| value definition. For example, the following configuration: | |
| ```hcl | |
| variable "moose" { | |
| type = string | |
| } | |
| ``` | |
| And the following `.tfvars` file: | |
| ```hcl | |
| mosse = "Moose" | |
| ``` | |
| Will cause OpenTofu to warn you that there is no variable declared `"mosse"`, which can help | |
| you spot this mistake. | |
| If you use `.tfvars` files across multiple configurations and expect to continue to see this warning, | |
| you can use the [`-compact-warnings`](../../cli/commands/plan.mdx#compact-warnings) | |
| option to simplify your output. | |
| If you provide values for undeclared variables on the [command line](#variables-on-the-command-line), | |
| OpenTofu will return an error. To avoid this error, either declare a variable block for the value, or remove | |
| the variable value from your OpenTofu call. | |
| ### Variable Definition Precedence | |
| The above mechanisms for setting variables can be used together in any | |
| combination. If the same variable is assigned multiple values, OpenTofu uses | |
| the _last_ value it finds, overriding any previous values. Note that the same | |
| variable cannot be assigned multiple values within a single source. | |
| OpenTofu loads variables in the following order, with later sources taking | |
| precedence over earlier ones: | |
| * Environment variables | |
| * The `terraform.tfvars` file, if present. | |
| * The `terraform.tfvars.json` file, if present. | |
| * Any `*.auto.tfvars` or `*.auto.tfvars.json` files, processed in lexical order | |
| of their filenames. | |
| * Any `-var` and `-var-file` options on the command line, in the order they | |
| are provided. | |
| :::warning Important | |
| Variables with map and object | |
| values behave the same way as other variables: the last value found overrides | |
| the previous values. This is a change from previous versions of OpenTofu, which | |
| would _merge_ map values instead of overriding them. | |
| ::: |