Skip to main content

How to Manage Secrets and Sensitive Data in Terraform

Key Takeaway

Best practices for managing secrets, passwords, and sensitive data in Terraform configurations. Step-by-step guide with code examples and best practices for ...

Table of Contents

The Problem With Secrets in Terraform

Terraform state files contain sensitive data in plain text. API keys, database passwords, and certificates stored in state are readable by anyone with state access. Here’s how to handle this securely.

Rule 1: Never Hardcode Secrets

# BAD - secret in code
resource "aws_db_instance" "db" {
  password = "super-secret-password"  # This ends up in state AND git
}

# GOOD - use a variable
resource "aws_db_instance" "db" {
  password = var.db_password
}

Method 1: Environment Variables

export TF_VAR_db_password="super-secret-password"
terraform apply

Method 2: AWS Secrets Manager

data "aws_secretsmanager_secret_version" "db_password" {
  secret_id = "prod/database/password"
}

resource "aws_db_instance" "db" {
  password = data.aws_secretsmanager_secret_version.db_password.secret_string
}

Method 3: HashiCorp Vault

provider "vault" {
  address = "https://vault.example.com"
}

data "vault_generic_secret" "db" {
  path = "secret/data/prod/database"
}

resource "aws_db_instance" "db" {
  password = data.vault_generic_secret.db.data["password"]
}

Method 4: SOPS Encrypted Files

# Encrypt a tfvars file
sops --encrypt --in-place secrets.tfvars

# Decrypt and apply
sops -d secrets.tfvars | terraform apply -var-file=/dev/stdin

Marking Outputs as Sensitive

output "db_connection_string" {
  value     = "postgresql://${var.db_user}:${var.db_password}@${aws_db_instance.db.endpoint}"
  sensitive = true
}

variable "db_password" {
  type      = string
  sensitive = true  # Prevents value from showing in plan output
}

State File Security

Even with these methods, sensitive values still exist in state. Protect state by:

  1. Encrypting state at rest — enable S3 SSE or use encrypted backends
  2. Restricting state access — IAM policies limiting who can read state
  3. Using Terraform Cloud — state is encrypted and access-controlled
  4. Never committing state to git — add *.tfstate to .gitignore

Best Practices Summary

  1. Never hardcode secrets in .tf files
  2. Use a secrets manager (AWS SM, Vault, Azure Key Vault)
  3. Mark sensitive variables and outputs with sensitive = true
  4. Encrypt state at rest and restrict access
  5. Rotate secrets regularly
  6. Use short-lived credentials (OIDC, STS) where possible

Learn More

🚀

Level Up Your Terraform Skills

Hands-on courses, books, and resources from Luca Berton

Luca Berton
Written by

Luca Berton

DevOps Engineer, AWS Partner, Terraform expert, and author. Creator of Ansible Pilot, Terraform Pilot, and CopyPasteLearn.