> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Defining Variables

> Explains declaring and using Terraform input variables to avoid hardcoding, enable reusable environment-agnostic configurations, and manage values securely through defaults, environment variables, tfvars, or CLI flags

This lesson explains how to define and use input variables in Terraform to make your configurations reusable and environment-agnostic.

Defining variables means declaring named inputs that Terraform configuration can reference instead of hardcoded values. Variables act as parameters, enabling the same Terraform code to be reused across environments (dev, staging, prod) by changing only the input values.

Hardcoded resource example
Below is an Azure Storage Account resource where key configuration values are hardcoded directly in the resource block. This will deploy successfully, but it tightly couples the resource to a single name, region, and resource group. Any change (for example, deploying to a different region) requires editing the Terraform code.

```hcl theme={null}
resource "azurerm_storage_account" "storage" {
  name                     = "satfworshop46536"
  location                 = "East US"
  resource_group_name      = "my-workshop-eus-rg"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}
```

Why this is brittle

* Hardcoded values prevent easy reuse across environments.
* Editing multiple resource blocks for a simple change is error-prone.
* Sharing or versioning configurations becomes harder.

Use variables to decouple values from resource blocks and centralize configuration.

Declaring and using variables
Create input variables in a `variables.tf` file and reference them using `var.<name>` from your resource files (`main.tf`, etc.).

Variables declaration (`variables.tf`):

```hcl theme={null}
# ---- variables.tf ----
variable "resource_group_name" {
  type        = string
  default     = "my-workshop-eus-rg"
  description = "Name of the resource group"
}

variable "location" {
  type        = string
  default     = "East US"
  description = "Azure region"
}
```

Use the variables in your resource (`main.tf`):

```hcl theme={null}
# ---- main.tf ----
resource "azurerm_storage_account" "storage" {
  name                      = "satfworshop46536"
  location                  = var.location
  resource_group_name       = var.resource_group_name
  account_tier              = "Standard"
  account_replication_type  = "LRS"
}

resource "azurerm_storage_account" "storage2" {
  name                      = "satfworshop48835"
  location                  = var.location
  resource_group_name       = var.resource_group_name
  account_tier              = "Standard"
  account_replication_type  = "LRS"
}
```

Referencing `var.location` and `var.resource_group_name` allows multiple resources to reuse the same inputs. If the region or resource group needs to change, update the variable defaults or supply different values at runtime in one place instead of editing every resource block.

<Callout icon="lightbulb" color="#1CB2FE">
  Variables can be provided by default values, environment variables, a `.tfvars` file, or via CLI flags when you run Terraform. This makes configurations portable and easier to manage across environments.
</Callout>

Common ways to provide variable values

| Source                    | Usage                                                  | Example                                                          |
| ------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------- |
| Default in `variables.tf` | Automatically used when no other value provided        | `default = "eastus"`                                             |
| Environment variable      | Prefix `TF_VAR_` to variable name                      | `export TF_VAR_region="eastus"`                                  |
| `*.tfvars` file           | Create a `terraform.tfvars` or custom file and pass it | `region = "eastus"` or `terraform apply -var-file="prod.tfvars"` |
| CLI `-var` flag           | Pass a value directly when running Terraform           | `terraform apply -var 'region=westus'`                           |

Demonstration: creating variables and resources in a project directory

* We'll create a small Terraform project that defines a provider, variables, and a single resource group resource.
* For brevity, this demo uses simpler variable names (`rg` and `region`) to illustrate the same concept.

Provider configuration (`provider.tf`):

```hcl theme={null}
provider "azurerm" {
  features {}
  subscription_id = "1b228746-75fd-46ed-8a6b-6a90666d6d3a"
}
```

Declare variables (`variables.tf`):

```hcl theme={null}
variable "rg" {
  default = "kodekloud-tf-var-rg"
}

variable "region" {
  default = "eastus"
}
```

Use variables in the resource group resource (`main.tf`):

```hcl theme={null}
resource "azurerm_resource_group" "rg" {
  name     = var.rg
  location = var.region
  tags     = {
    environment = "testing"
  }
}
```

Initialize the working directory and inspect the plan:

```bash theme={null}
terraform init
terraform plan
```

Sample `terraform init` output:

```plaintext theme={null}
Terraform has been successfully initialized!
```

Sample `terraform plan` output:

```plaintext theme={null}
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

# azurerm_resource_group.rg will be created
+ resource "azurerm_resource_group" "rg" {
    + id       = (known after apply)
    + location = "eastus"
    + name     = "kodekloud-tf-var-rg"
    + tags     = {
        + "environment" = "testing"
      }
  }

Plan: 1 to add, 0 to change, 0 to destroy.
```

Note that the plan shows the resolved values (for example, `eastus` and `kodekloud-tf-var-rg`) rather than `var.rg` or `var.region`. This makes it easy to review what Terraform will deploy.

<Callout icon="warning" color="#FF6B6B">
  Do not store sensitive secrets (API keys, passwords) in plaintext `variables.tf` defaults or checked-in `.tfvars` files. Use environment variables, Terraform Cloud/Enterprise workspace variables, or secret management integrations to protect sensitive data.
</Callout>

Quick reference: variable block essentials

| Argument      | Description                                                                         | Example                        |
| ------------- | ----------------------------------------------------------------------------------- | ------------------------------ |
| `type`        | Optional: enforce a data type (`string`, `number`, `bool`, `list`, `map`, `object`) | `type = string`                |
| `default`     | Optional: value used when no other value supplied                                   | `default = "eastus"`           |
| `description` | Optional: helpful text for maintainers                                              | `description = "Azure region"` |
| `sensitive`   | Optional: mark value as sensitive to hide in output                                 | `sensitive = true`             |

Summary

* Declaring variables decouples configuration values from resource blocks, improving reusability and maintainability.
* Use `var.<name>` in resource blocks to reference declared variables.
* Variable values can be supplied via defaults, environment variables (`TF_VAR_`), `.tfvars` files, or CLI `-var` flags.
* For secrets, avoid checked-in defaults and prefer secure secret mechanisms.

Further reading and references

* [Terraform Input Variables](https://www.terraform.io/language/values/variables)
* [Terraform CLI - var files](https://www.terraform.io/cli/commands#apply)
* [Azure Provider (azurerm) on Terraform Registry](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)

A deeper dive into the `variable` block would cover advanced topics such as type constraints, `validation` blocks, `sensitive` attributes, and multiple ways to provide variable values across CI/CD and team workflows.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/terraform-on-azure/module/6909fa70-4ccc-40c3-a918-1188673d8985/lesson/4499ac01-c650-4fa8-b55c-f75a90691478" />
</CardGroup>
