Guide: Managing Environment Variables in Terraform
This guide provides an overview of managing environment variables in Terraform, covering two common approaches (using a single environments.auto.tfvars
file and separate environment files), as well as an alternative approach with Terraform Workspaces. Additionally, the guide evaluates best practices for selecting the most suitable method based on project complexity and environment isolation requirements.
Method 1: Using a Single environments.auto.tfvars
File
In this approach, all environment configurations are defined within a single .tfvars
file, named environments.auto.tfvars
. This file automatically loads into the Terraform configuration, making it convenient to manage all environment variables in one location.
Step 1: Create environments.auto.tfvars
Example content for environments.auto.tfvars
:
environments = {
development = {
account_id = "123456789101112"
route53_zone = "development.app.company.com"
win_ami_name = "windowsServer-2022-123456"
rhel_ami_name = "LinuxServer-v8.8-123647"
instance_config = {
instance_1 = {
itype = "t3.2xlarge"
vol_size = 100
}
}
}
preproduction = {
account_id = "111245650234"
route53_zone = "preproduction.app.company.com"
win_ami_name = "windowsServer-2022-123455"
rhel_ami_name = "LinuxServer-v8.8-123646"
instance_config = {
instance_1 = {
itype = "t3.2xlarge"
vol_size = 100
}
}
}
production = {
account_id = "9999354632345"
route53_zone = "production.app.company.com"
win_ami_name = "windowsServer-2022-123455"
rhel_ami_name = "LinuxServer-v8.8-123646"
instance_config = {
instance_1 = {
itype = "t3.4xlarge"
vol_size = 1000
}
}
}
}
Each environment is created and in this example, we have the account_id which would be something like the AWS account id. The Route53 zone address, a Windows and Linux AMI Name. Then we open up a section for the instance settings.
Step 2: Define the Variables in variables.tf
To accommodate the structure in environments.auto.tfvars
, add the following in variables.tf
:
variable "environment" {
type = string
description = "Used to set the environment"
}
variable "environments" {
type = map(object({
account_id = string
route53_zone = string
win_ami_name = string
rhel_ami_name = string
instance_config = map(object({
itype = string
vol_size = number
}))
}))
}
Create a locals.tf file if you don’t have one, and add the whole block of code. If you already have a locals.tf file just copy the config line in to it.
locals {
config = var.environments[var.environment]
}
Set an environment variable on your machine. In Lunix it will be:-
export environment=development
And Windows, PowerShell, (you will need to close PowerShell and reopen it to see the variable) will be:-
[Environment]::SetEnvironmentVariable("environment", "development", "Machine")
Method 2: Separate Environment Files for Each Environment
In this method, you create a separate .tfvars
files for each environment (e.g., development.tfvars
, preproduction.tfvars
, production.tfvars
). This provides isolated files, which improves clarity and reduces risk in production-critical settings.
Alternative Approach: Use Terraform Workspaces
Terraform Workspaces allow you to manage different states for different environments. Workspaces are particularly useful for isolating environment state files (e.g., one state for development
, another for production
), which can prevent accidental cross-environment contamination.
How to Use Workspaces:
- Define Environment-Specific Variables with Workspaces: Use a single
terraform.tfvars
file to define general variables, and then add environment-specific.tfvars
files that load based on the active workspace. - Switch Between Workspaces: Create and switch to new workspaces:
terraform workspace new development
terraform apply -var-file="development.tfvars"
- Use the Workspace Variable: Access the current workspace name directly in your configuration:
locals {
current_env = terraform.workspace
}
output "instance_type" {
value = var.environments[local.current_env].instance_config.instance_1.itype
}
Comparison of Best Practice Approaches
Approach | Use Case | Pros | Cons |
---|---|---|---|
Single environments.auto.tfvars | Simple projects with minimal complexity | Easy to manage in a single file, convenient for small teams or low-risk environments | Risk of accidental changes affecting other environments, less control over isolation |
Separate Environment Files | More complex projects, critical environments | Stronger environment isolation, clearer configuration management | Requires more management, harder to maintain across many environments |
Terraform Workspaces | Strict environment isolation requirements | State isolation, automatic environment selection | Limited to isolated environments; not ideal for branching or dynamic environments |
Conclusion: Best Practices Recommendation
- Simple Setups: Using a single
environments.auto.tfvars
may be sufficient, especially in low-risk environments. - Complex Environments: For complex infrastructure or critical environments, separate environment files give better clarity and control.
- Robust Isolation: If you need robust isolation of state files and have limited environments (e.g.,
development
,staging
,production
), Terraform workspaces are an effective solution.
Using separate environment files in conjunction with workspaces provides both the clarity of isolated files and the safety of workspace-based state separation, making it a powerful combination for larger projects or multi-team setups.