Terraform Variable Files
Introduction
When working with Terraform to manage your infrastructure as code, you'll often need to define and use variables to make your configurations more flexible and reusable. As your projects grow in complexity, managing these variables directly in your configuration files can become unwieldy. This is where Terraform variable files come into play.
Variable files allow you to separate your variable values from your Terraform configuration, making your code more organized, maintainable, and adaptable to different environments. In this guide, we'll explore how to use variable files effectively in your Terraform projects.
What Are Terraform Variable Files?
Terraform variable files are separate files that contain variable values which can be loaded into your Terraform configuration during execution. These files typically use the .tfvars
or .tfvars.json
extension and follow a specific syntax to define variable values.
Variable files help you:
- Separate configuration from variable values
- Maintain different sets of values for different environments
- Share non-sensitive variable values with team members
- Keep sensitive values outside of version control
Basic Syntax and Usage
Creating a Variable File
Let's start by creating a simple variable file. By convention, these files are named with the .tfvars
extension, with terraform.tfvars
being automatically loaded by Terraform.
Create a file named terraform.tfvars
with the following content:
region = "us-west-2"
instance_type = "t2.micro"
instance_count = 2
Defining Variables in Your Terraform Configuration
Before using the variables from your variable file, you need to declare them in your Terraform configuration files:
variable "region" {
description = "AWS region to deploy resources"
type = string
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.nano"
}
variable "instance_count" {
description = "Number of instances to create"
type = number
default = 1
}
Using the Variables
With the variables defined and their values set in the variable file, you can use them in your Terraform configuration:
provider "aws" {
region = var.region
}
resource "aws_instance" "example" {
count = var.instance_count
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type
tags = {
Name = "example-instance-${count.index + 1}"
}
}
When you run terraform apply
, Terraform automatically loads the values from terraform.tfvars
.
Variable File Loading Order
Terraform loads variables in a specific order, with later sources taking precedence over earlier ones:
- Environment variables
terraform.tfvars
file (if present)terraform.tfvars.json
file (if present)- Any
*.auto.tfvars
or*.auto.tfvars.json
files, processed in lexical order - Any
-var
and-var-file
options on the command line, in the order they are provided
This loading order gives you flexibility in how you organize and override variable values.
Using Multiple Variable Files
One of the key benefits of variable files is the ability to maintain different sets of values for different environments or scenarios.
Environment-Specific Variable Files
Let's say you want to maintain separate configurations for development, staging, and production environments:
dev.tfvars:
region = "us-west-2"
instance_type = "t2.micro"
instance_count = 1
staging.tfvars:
region = "us-west-2"
instance_type = "t2.medium"
instance_count = 2
prod.tfvars:
region = "us-east-1"
instance_type = "m5.large"
instance_count = 3
To use a specific variable file, you can use the -var-file
flag with the Terraform CLI:
# For development environment
terraform apply -var-file=dev.tfvars
# For staging environment
terraform apply -var-file=staging.tfvars
# For production environment
terraform apply -var-file=prod.tfvars
Auto-loaded Variable Files
If you name your variable file with the .auto.tfvars
extension, Terraform will automatically load it without requiring the -var-file
flag. This can be useful for variables that are common across environments but not included in the default terraform.tfvars
file:
common.auto.tfvars:
project_name = "my-awesome-project"
team = "infrastructure"
Variable File Formats
Terraform supports two main formats for variable files:
HCL Format (.tfvars)
The most common format uses Terraform's native HCL (HashiCorp Configuration Language) syntax:
string_var = "hello"
number_var = 42
bool_var = true
list_var = [
"item1",
"item2"
]
map_var = {
key1 = "value1"
key2 = "value2"
}
JSON Format (.tfvars.json)
You can also use JSON format for your variable files:
{
"string_var": "hello",
"number_var": 42,
"bool_var": true,
"list_var": [
"item1",
"item2"
],
"map_var": {
"key1": "value1",
"key2": "value2"
}
}
JSON format can be particularly useful when generating variable files programmatically or integrating with other tools.
Practical Example: Multi-Environment AWS Deployment
Let's walk through a practical example of using variable files for a multi-environment AWS deployment:
File Structure:
project/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars # Default/common variables
├── dev.tfvars # Development environment
├── staging.tfvars # Staging environment
└── prod.tfvars # Production environment
variables.tf
variable "environment" {
description = "Deployment environment"
type = string
}
variable "region" {
description = "AWS region"
type = string
}
variable "instance_type" {
description = "EC2 instance type"
type = string
}
variable "instance_count" {
description = "Number of instances"
type = number
default = 1
}
variable "tags" {
description = "Tags to apply to all resources"
type = map(string)
default = {}
}
terraform.tfvars (Common Variables)
tags = {
project = "terraform-demo"
managed_by = "terraform"
}
dev.tfvars
environment = "development"
region = "us-west-2"
instance_type = "t2.micro"
instance_count = 1
tags = {
environment = "dev"
criticality = "low"
}
staging.tfvars
environment = "staging"
region = "us-west-2"
instance_type = "t2.medium"
instance_count = 2
tags = {
environment = "staging"
criticality = "medium"
}
prod.tfvars
environment = "production"
region = "us-east-1"
instance_type = "m5.large"
instance_count = 3
tags = {
environment = "prod"
criticality = "high"
}
main.tf
provider "aws" {
region = var.region
}
locals {
# Merge the common tags with environment-specific tags
all_tags = merge(var.tags, {
environment = var.environment
})
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = local.all_tags
}
resource "aws_instance" "app_servers" {
count = var.instance_count
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type
tags = merge(local.all_tags, {
Name = "${var.environment}-app-${count.index + 1}"
})
}
Applying the Configuration
To deploy to the development environment:
terraform apply -var-file=dev.tfvars
To deploy to staging:
terraform apply -var-file=staging.tfvars
To deploy to production:
terraform apply -var-file=prod.tfvars
This approach allows you to maintain a single Terraform configuration that can be applied to different environments by simply changing the variable file.
Working with Sensitive Variables
Variable files are great for organizing your configuration, but be cautious about storing sensitive data like passwords or API keys in them, especially if they're committed to version control.
Best Practices for Sensitive Variables
-
Use
.gitignore
: Add*.tfvars
to your.gitignore
file to prevent accidental commits. -
Use environment variables for sensitive values:
bashexport TF_VAR_database_password="super-secret-password"
-
Use secret management tools like AWS Secrets Manager, HashiCorp Vault, or environment-specific CI/CD secrets.
-
Mark variables as sensitive in your variable declarations:
hclvariable "database_password" {
description = "Password for database"
type = string
sensitive = true
}
Variable Files in CI/CD Pipelines
When working with CI/CD pipelines, variable files become even more valuable:
-
Environment-specific deployments: Store different
.tfvars
files for each environment. -
Generated variable files: Some CI/CD systems can generate
.tfvars
files dynamically before deployment. -
Variable file templates: Use templates that get populated with environment-specific values:
hcl# template.tfvars
region = "{{REGION}}"
instance_type = "{{INSTANCE_TYPE}}" -
Secret injection: Inject secrets from secure storage into your variable files during the deployment process.
Visualizing Variable Resolution
To better understand how Terraform resolves variables from different sources, here's a simple flow diagram:
Summary
Terraform variable files are a powerful feature that helps you organize your infrastructure code and make it more maintainable and reusable. By separating your variable values from your configuration, you can:
- Maintain different sets of values for different environments
- Keep sensitive information out of your main configuration files
- Make your Terraform code more organized and easier to manage
- Enable better collaboration within your team
When working with variable files, remember:
- Use
terraform.tfvars
for default variable values - Use environment-specific
.tfvars
files with the-var-file
flag - Use
.auto.tfvars
for automatically loaded variables - Be careful with sensitive data in variable files
- Understand the variable loading order to avoid unexpected behaviors
Additional Resources and Exercises
Exercises
-
Basic Variable File: Create a simple Terraform configuration with variables for AWS region, instance type, and instance count. Define these variables in a
.tfvars
file and apply the configuration. -
Multi-Environment Setup: Extend your configuration to support development, staging, and production environments using separate variable files.
-
Variable Precedence: Experiment with defining the same variable in multiple places (environment variables, different
.tfvars
files, command line) to observe Terraform's precedence rules. -
Sensitive Variables: Practice handling sensitive variables securely using Terraform's
sensitive
attribute and appropriate storage methods.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)