How to Manage Secrets and Sensitive Data in Terraform
Best practices for managing secrets, passwords, and sensitive data in Terraform configurations. Step-by-step guide with code examples and best practices for ...
Troubleshooting
Fix the Terraform output refers to sensitive values error. Covers sensitive outputs, nonsensitive function, module outputs, and secrets management patterns.
Add sensitive = true to the output block, or use nonsensitive() if you intentionally want to expose the value. Terraform prevents accidental exposure of sensitive data in outputs.
Error: Output refers to sensitive values
on outputs.tf line 1:
1: output "db_connection_string" {
To reduce the risk of accidentally exporting sensitive data that was
intended to be only internal, Terraform requires that any root module
output containing sensitive data be explicitly marked as sensitive.Terraform tracks which values are "sensitive" — marked either in variable definitions or by provider attributes. When you reference a sensitive value in an output without marking the output as sensitive, Terraform blocks it to prevent accidental exposure.
# Variable marked sensitive
variable "db_password" {
type = string
sensitive = true
}
# Provider attribute marked sensitive (automatic)
# aws_db_instance.main.password is always sensitive
# Output referencing sensitive value without sensitive = true
output "db_password" {
value = var.db_password # ERROR — sensitive value in non-sensitive output
}output "db_connection_string" {
value = "postgresql://${var.db_user}:${var.db_password}@${aws_db_instance.main.endpoint}/mydb"
sensitive = true
}
output "db_password" {
value = var.db_password
sensitive = true
}
# Access the value later:
# terraform output -json db_password
# terraform output -raw db_passwordIf the value isn't actually secret (e.g., a generated resource name):
output "db_endpoint" {
# The endpoint itself isn't secret, but it's derived from a sensitive resource
value = nonsensitive(aws_db_instance.main.endpoint)
}
# Only use nonsensitive() when you've verified the value isn't actually secret# Non-sensitive outputs
output "db_endpoint" {
value = aws_db_instance.main.endpoint
description = "Database endpoint"
}
output "db_port" {
value = aws_db_instance.main.port
description = "Database port"
}
# Sensitive outputs
output "db_password" {
value = aws_db_instance.main.password
sensitive = true
description = "Database master password"
}
output "db_connection_string" {
value = "postgresql://${var.db_user}:${random_password.db.result}@${aws_db_instance.main.endpoint}:${aws_db_instance.main.port}/mydb"
sensitive = true
}For production, store secrets in a secrets manager:
resource "random_password" "db" {
length = 24
special = true
}
resource "aws_secretsmanager_secret" "db_password" {
name = "${var.project}-db-password"
}
resource "aws_secretsmanager_secret_version" "db_password" {
secret_id = aws_secretsmanager_secret.db_password.id
secret_string = random_password.db.result
}
# Output the secret ARN (not sensitive) instead of the password
output "db_password_secret_arn" {
value = aws_secretsmanager_secret.db_password.arn
description = "ARN of the Secrets Manager secret containing the DB password"
}When a child module outputs sensitive values:
# modules/database/outputs.tf
output "password" {
value = random_password.db.result
sensitive = true
}
# Root module
module "database" {
source = "./modules/database"
}
# Must also be sensitive in root
output "db_password" {
value = module.database.password
sensitive = true
}# Sensitive outputs show as <sensitive> in normal output
terraform output
# db_password = <sensitive>
# Use -json to see the actual value
terraform output -json db_password
# Use -raw for plain text (scripts)
terraform output -raw db_password
# In CI/CD pipelines
DB_PASS=$(terraform output -raw db_password)sensitive = truenonsensitive()sensitive = truerandom_password for generated credentials — automatically marked sensitive.terraform.tfstate encryption — state files contain all output values in plaintextTerraform blocks sensitive values from appearing in non-sensitive outputs to prevent accidental exposure. Add sensitive = true to the output, use nonsensitive() only for values that aren't actually secret, and consider storing passwords in AWS Secrets Manager or HashiCorp Vault instead of passing them through Terraform outputs.
Best practices for managing secrets, passwords, and sensitive data in Terraform configurations. Step-by-step guide with code examples and best practices for ...
Fix the Terraform 'Backend configuration changed' error. Migrate state between backends (local to S3, S3 to S3), resolve lock conflicts
Fix Terraform provider version conflicts between modules, lock files, and constraint mismatches. Resolve dependency lock errors, upgrade providers safely
Fix the Terraform 'Reference to undeclared resource' error. Causes include typos, missing resources, wrong module references, and for_each/count confusion.