There’s a moment in every Terraform project where hardcoding values starts to feel wrong. Maybe it’s a database password, an environment-specific region, or just something that shouldn’t live in version control. That’s where environment variables quietly become one of the most useful tools in your Terraform workflow.
Instead of passing variables through CLI flags or committing .tfvars files, Terraform allows you to inject values using environment variables—with a simple naming convention.
The Quick Idea
Terraform automatically reads environment variables that follow this pattern:
TF_VAR_<variable_name>
If your Terraform configuration defines a variable like this:
1variable "region" {
2 type = string
3}You can set its value using an environment variable:
1export TF_VAR_region="us-west-1"Terraform will pick this up automatically when you run terraform plan or terraform apply.
Why Use Environment Variables?
Let’s break down where this approach shines.
- No sensitive data in code — great for secrets like API keys or passwords
- CI/CD friendly — works naturally with pipelines and secret managers
- No extra files — avoids managing multiple
.tfvarsfiles - Easy overrides — quick changes without modifying code
Here’s where things get interesting: environment variables sit at a specific level in Terraform’s variable precedence hierarchy. They override defaults in your .tf files but are overridden by CLI flags like -var.
A Real Example
Imagine a simple AWS setup:
1variable "instance_type" {
2 type = string
3 default = "t2.micro"
4}
5
6resource "aws_instance" "example" {
7 ami = "ami-123456"
8 instance_type = var.instance_type
9}Now, instead of editing the code, you can dynamically change the instance type:
1export TF_VAR_instance_type="t3.medium"
2terraform applyNo code changes, no additional files—just a runtime override.
Multiple Variables? No Problem
You can define as many environment variables as needed:
1export TF_VAR_region="us-east-1"
2export TF_VAR_instance_type="t3.large"
3export TF_VAR_environment="staging"Terraform will map each one to its corresponding variable block.
Handling Complex Types
Environment variables aren’t limited to simple strings. You can pass lists and maps using JSON syntax.
Example: list
1variable "availability_zones" {
2 type = list(string)
3}1export TF_VAR_availability_zones='["us-east-1a","us-east-1b"]'Example: map
1variable "tags" {
2 type = map(string)
3}1export TF_VAR_tags='{"env":"dev","team":"platform"}'This JSON-based approach is powerful but easy to get wrong—especially with quoting—so test carefully.
Common Mistakes Developers Make
A few gotchas show up frequently when using Terraform environment variables:
- Forgetting the TF_VAR_ prefix — Terraform won’t recognize the variable
- Mismatched names — must exactly match the variable block name
- Incorrect JSON formatting — especially for lists and maps
- Shell escaping issues — different shells handle quotes differently
If something doesn’t seem to work, run terraform plan and inspect the values Terraform is actually using.
Environment Variables in CI/CD Pipelines
This is where environment variables really earn their place.
In tools like GitHub Actions, GitLab CI, or Jenkins, you can define secrets and inject them directly:
1TF_VAR_db_password=${{ secrets.DB_PASSWORD }}This keeps sensitive data out of your repository while still allowing Terraform to consume it.
Many teams combine this with secret managers like AWS Secrets Manager or Vault for even tighter control.
When Not to Use Environment Variables
Despite their convenience, they’re not always the best choice.
- Large configurations — JSON strings can become unreadable
- Shared team setups — harder to track than versioned
.tfvarsfiles - Debugging complexity — invisible values can slow troubleshooting
In those cases, a combination of .tfvars files and environment variables often works better.
A Practical Workflow
Many teams settle on something like this:
- Use
.tfdefaults for safe baseline values - Use
.tfvarsfor non-sensitive environment configs - Use
TF_VAR_*environment variables for secrets and overrides
This layered approach keeps things flexible without becoming chaotic.
Final Thought
Setting Terraform variables using environment variables is one of those small techniques that scales surprisingly well. It reduces friction, keeps sensitive data out of your codebase, and fits naturally into automated pipelines.
Once you start using TF_VAR_* consistently, it becomes second nature—and hard to go back.