Consistence File Structure:
It is recommended to have separate directories for different purposes. Use a consistent format, style & code structure.
-- PROJECT-DIRECTORY/
-- modules/
-- <service1-name>/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README
-- <service2-name>/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README
-- ...other…
-- environments/
-- dev/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvars
-- qa/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvars
-- stage/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvars
-- prod/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvarsPutting all code in main.tf is not a good idea, better having several files like:
main.tf- call modules, locals, and data sources to create all resources.variables.tf- contains declarations of variables used inmain.tfoutputs.tf- contains outputs from the resources created inmain.tfversions.tf- contains version requirements for Terraform and providers.terraform.tfvars- contains variables values and should not be used anywhere.
Follow a standard module structure:
https://developer.hashicorp.com/terraform/language/modules/develop
Use remote state:
- Never to store the state file on your local machine or version control.
- State file may include sensitive values in plain text, representing a security risk, anyone with access to your machine or this file can potentially view it.
- With remote state, Terraform writes the state data to a remote data store, which can be shared between all team members. This approach locks the state to allow for collaboration as a team.
- Configure Terraform backend using remote state (shared locations) services such as Amazon S3, Azure Blob Storage, GCP Cloud Storage, Terraform Cloud.
- It also separates the state and all the potentially sensitive information from version control.
- Don’t commit the .tfstate file source control. To prevent accidentally committing development state to source control, use gitignore for Terraform state files.
- Manipulate state only through the commands.
- Encrypt state: Even though no secrets should be in the state file, always encrypt the state as an additional measure of defense.
- Keep your backends small.
- Back up your state files.
- Use one state per environment.
Setup backend state locking:
-
There can be multiple scenarios where more than one developer tries to run the terraform configuration at the same time. This can lead to the corruption of the terraform state file or even data loss.
-
As multiple users access the same state file, the state file should be locked when it is in use. The locking mechanism helps to prevent such scenarios. It makes sure that at a time, only one person is running the terraform configurations, and there is no conflict.
-
Not all backend support locking. e.g. Azure Blob storage natively supports locking, while Amazon S3 supports using DynamoDB in AWS.
terraform {
backend "s3" {
bucket = "YOUR_S3_BUCKET_NAME"
dynamodb_table = "YOUR_DYNAMODB_TABLE_NAME"
key = "prod_terraform.tfstate"
region = "us-east-1"
# Authentication
profile = "MY_PROFILE"
}
}Don’t store secrets in state
- There are many resources and data providers in Terraform that store secret values in plaintext in the state file. Where possible, avoid storing secrets in state.
- Also, never commit secrets to source control, including in Terraform configuration.
- Instead, upload them to a system like AWS Secret Manager, Azure Key Vault, GCP Secret Manager, HashiCorp Vault, and reference them by using data sources.