How to Securely Store API Keys in Terraform (Don't Commit Secrets to Git)
Everyone understands you shouldn't expose secrets. When I started using Terraform with Cloudflare and AWS, I needed to manage API tokens without hardcoding them into my .tf files. Here's what I learned about securely storing secrets in Terraform projects.
The Problem - Don't Do This
provider "cloudflare" {
api_token = "abc123secrettoken" # ❌ Never do this
}
If you commit this to GitHub, your secrets are exposed forever — even if you delete the file later, it stays in git history.
So What Should You Do?
Let the Cloudflare provider auto-detect the env var directly:
provider "cloudflare" {
# No api_token here
# Provider automatically reads CLOUDFLARE_API_TOKEN from environment
}
Terraform automatically reads certain environment variables. Create a .env file:
# .env
export CLOUDFLARE_API_TOKEN="your-token-here"
Load it before running Terraform:
source .env
terraform plan
What Goes Where?
Secrets (in .env, never commit):
API tokens
Access keys
Passwords
Config (in terraform.tfvars, safe to commit):
region = "eu-west-2"cloudflare_zone_id = "abc123"(zone IDs aren't secret)
Don't Forget .gitignore
.env
*.tfvars
*.tfstate
*.tfstate.backup
Why ignore state files? Even with environment variables, if you pass secrets through Terraform variables, they appear in plaintext in
terraform.tfstate. Never commit state files.
What I Built
I used this approach for deploying my app on AWS with Cloudflare DNS. Environment variables for secrets, terraform.tfvars for config. Check out the repository structure here.
Key Takeaway
Never hardcode secrets. Use environment variables locally, and let providers auto-detect them to keep secrets out of your state file entirely. If you do happen to expose them, rotate immediately.
