Terraform pre-commit Hooks: Installation, Configuration, TFLint, Trivy, Checkov & CI/CD Guide
Learn to configure pre-commit for Terraform with step-by-step commands, terraform fmt, validate, TFLint, Trivy, Checkov, terraform-docs, provider locks, multi-environment projects, and GitHub Actions.
Terraform pre-commit, pre-commit Terraform configuration, terraform_fmt, terraform_validate, terraform_tflint, terraform_trivy, terraform_docs, Terraform security scanning, Terraform Git hooks, Terraform CI/CD best practices
1. Introduction
Terraform is widely used to provision and manage cloud infrastructure through Infrastructure as Code (IaC).
As Terraform repositories grow, maintaining consistent formatting, validating configurations, enforcing security standards, and keeping documentation updated become increasingly important.
Consider a development team managing Terraform resources for AWS, Azure, Google Cloud, Kubernetes, or MongoDB Atlas.
Without automated checks, developers may accidentally commit:
- Incorrectly formatted Terraform configurations.
- Invalid provider or module references.
- Deprecated or unsupported arguments.
- Unrestricted network security rules.
- Unencrypted cloud resources.
- Hardcoded credentials.
- Terraform modules with outdated documentation.
- Inconsistent provider lock files.
- Changes that fail validation in CI/CD.
Many of these problems can be detected before changes reach the main branch.
The pre-commit framework, combined with the community-maintained pre-commit-terraform hook collection, provides a practical solution.
Instead of manually executing multiple Terraform commands before every commit, developers can automate these checks through Git hooks.
In this tutorial, we will configure a complete Terraform quality-control workflow, starting with formatting and expanding into validation, linting, security scanning, documentation, and CI/CD enforcement.
2. How pre-commit Works with Terraform
pre-commit is a framework that executes configured checks when Git operations occur.
Terraform-specific hooks can call tools including:
- Terraform CLI
- TFLint
- Trivy
- Checkov
- terraform-docs
- Infracost
- Terragrunt
- OpenTofu
The checks are configured in a file named:
.pre-commit-config.yamlCode language: CSS (css)
Terraform Development Workflow
Developer modifies Terraform files
|
v
git add *.tf
|
v
git commit
|
v
pre-commit hooks
|
+-------+-------+
| |
v v
terraform fmt TFLint
| |
+-------+-------+
|
v
Generate Docs
|
v
Commit permitted?
/ \
Yes No
| |
v v
Git commit Fix issues
| |
| Stage and retry
v
git push
|
v
pre-push hooks
|
+----+-------+
| |
v v
Validate Trivy
| |
+-----+------+
|
v
CI/CD checks
|
v
Pull request
|
v
Code review
|
v
Terraform plan
|
v
Approved apply
The goal is not to run every possible check on every commit.
A more efficient workflow divides checks according to their execution cost.
| Stage | Checks | Typical cost |
|---|---|---|
| Pre-commit | Terraform formatting, whitespace, basic linting | Low |
| Pre-commit | Documentation generation | LowโMedium |
| Pre-push | Terraform validation | MediumโHigh |
| Pre-push | Security scanning | MediumโHigh |
| CI/CD | Complete validation and security checks | Variable |
| Deployment pipeline | Terraform plan and policy evaluation | Potentially expensive |
| Approved deployment | Terraform apply | Infrastructure-changing |
Recommended approach: Keep local commits fast and enforce all required checks again in CI/CD.
3. Prerequisites
Before configuring pre-commit for Terraform, install the required tools.
| Tool | Purpose | Required? |
|---|---|---|
| Git | Source control and Git hooks | Yes |
| Python 3.11+ | Runtime for pre-commit 4.7.0 | Yes |
| pre-commit | Git hook framework | Yes |
| Terraform CLI | Terraform formatting and validation | Yes |
| Bash | Required by pre-commit-terraform shell hooks | Yes |
| TFLint | Advanced Terraform linting | Optional |
| terraform-docs | Generate module documentation | Optional |
| Trivy | Detect Terraform security misconfigurations | Optional |
| Checkov | Additional IaC policy scanning | Optional |
| jq | Certain hook recovery and cost workflows | Optional |
Check installed versions:
git --version
python3 --version
pre-commit --version
terraform version
For additional tools:
tflint --version
terraform-docs --version
trivy --version
checkov --version
Install only the additional tools used by your configured hooks.
4. Install Terraform pre-commit Dependencies on macOS
The following commands work on supported Intel and Apple Silicon Macs.
Step 1: Check Homebrew
brew --version
Install Homebrew from its official website if necessary:
Step 2: Install pre-commit
brew install pre-commit
Step 3: Install Terraform
Add HashiCorp’s official tap:
brew tap hashicorp/tap
Install Terraform:
brew install hashicorp/tap/terraform
Step 4: Install TFLint
brew install terraform-linters/tap/tflint
Step 5: Install terraform-docs
brew install terraform-docs
Step 6: Install Trivy
brew install trivy
Step 7: Install Checkov (Optional)
Use pipx:
brew install pipx
pipx ensurepath
pipx install checkov
Open a new terminal if PATH changes require it.
Step 8: Verify Installation
pre-commit --version
terraform version
tflint --version
terraform-docs --version
trivy --version
checkov --version
You now have the principal tools used in this tutorial.
5. Install Terraform pre-commit Dependencies on Linux
These instructions apply to Ubuntu and Debian. RHEL and other Linux systems can use the corresponding package managers and official binary distributions.
Step 1: Install Git, Python, and pipx
sudo apt update
sudo apt install -y \
git \
python3 \
python3-pip \
python3-venv \
pipx \
curl \
unzip \
jq
Ensure the selected Python version is 3.11 or newer.
Step 2: Install pre-commit
pipx ensurepath
Open a new shell if required.
pipx install pre-commit
Step 3: Install Terraform
Install Terraform using HashiCorp’s official Linux installation instructions:
For supported Ubuntu/Debian systems, HashiCorp provides an APT repository.
After configuring that repository:
sudo apt update
sudo apt install terraform
Step 4: Install TFLint
Download the appropriate Linux package from:
Choose the binary matching your CPU architecture, verify the checksum or published artifact attestation, and install the binary in a directory on PATH.
For example, after extracting the downloaded Linux binary:
sudo install -m 0755 tflint /usr/local/bin/tflint
Step 5: Install terraform-docs
Download the appropriate package from:
After extraction:
sudo install -m 0755 terraform-docs /usr/local/bin/terraform-docs
Step 6: Install Trivy
Use the official installation instructions:
After configuring Trivy’s official APT repository:
sudo apt update
sudo apt install trivy
Step 7: Install Checkov (Optional)
pipx install checkov
Step 8: Verify
pre-commit --version
terraform version
tflint --version
terraform-docs --version
trivy --version
For RHEL, CentOS Stream, Rocky Linux, and Fedora, use compatible RPM packages or official binary releases rather than assuming Debian packages will work.
6. Configure Terraform pre-commit on Windows
Windows deserves special attention.
Although pre-commit itself supports native Windows, the pre-commit-terraform hook collection executes Bash scripts.
The maintainers strongly recommend WSL2 with Ubuntu or Docker for Windows users.
Recommended: WSL2
Open PowerShell as Administrator.
Install WSL:
wsl --install -d Ubuntu
Restart Windows if prompted.
Open the Ubuntu terminal and install the Linux dependencies using the instructions in Section 5.
For better compatibility and performance, keep active Terraform repositories inside the WSL Linux filesystem, such as:
~/projects/terraform-infrastructureCode language: JavaScript (javascript)
Rather than placing the working repository under /mnt/c, unless your workflow requires Windows filesystem access.
Alternative: Docker
The community-maintained hook collection provides a Docker image containing Terraform-related tools.
For an initial evaluation:
docker pull ghcr.io/antonbabenko/pre-commit-terraform:latest
Run the checks from a Git repository on Linux or WSL:
docker run --rm \
-e "USERID=$(id -u):$(id -g)" \
-v "$(pwd):/lint" \
-w /lint \
ghcr.io/antonbabenko/pre-commit-terraform:latest \
run --all-filesCode language: JavaScript (javascript)
The Docker image’s latest tag is convenient for testing but is not a reproducible production dependency. Pin a reviewed image version or digest for CI/CD.
Native Windows using Git Bash is possible, but has additional PATH, Bash, and tool compatibility requirements.
7. Create a Terraform Repository Structure
A well-organized Terraform repository makes hook configuration simpler.
Consider the following example:
terraform-infrastructure/
โ
โโโ .gitignore
โโโ .pre-commit-config.yaml
โโโ .tflint.hcl
โ
โโโ modules/
โ โโโ vpc/
โ โ โโโ main.tf
โ โ โโโ variables.tf
โ โ โโโ outputs.tf
โ โ โโโ README.md
โ โ
โ โโโ eks/
โ โโโ main.tf
โ โโโ variables.tf
โ โโโ outputs.tf
โ โโโ README.md
โ
โโโ environments/
โ โโโ development/
โ โ โโโ main.tf
โ โ โโโ versions.tf
โ โ โโโ terraform.tfvars.example
โ โ
โ โโโ staging/
โ โ โโโ main.tf
โ โ โโโ versions.tf
โ โ
โ โโโ production/
โ โโโ main.tf
โ โโโ versions.tf
โ
โโโ .github/
โโโ workflows/
โโโ terraform-quality.yml
This structure separates reusable modules from environment-specific root configurations.
The paths are examples. Adapt the directory filters in subsequent sections to match your actual repository.
8. Use Case 1: Automatically Format Terraform Code
Formatting is the first and most useful Terraform pre-commit use case.
Terraform provides:
terraform fmt
To format all Terraform files under the current directory:
terraform fmt -recursive
To check formatting without modifying files:
terraform fmt -check -recursive
To display formatting differences:
terraform fmt -check -diff -recursive
Configure terraform_fmt in pre-commit
Create .pre-commit-config.yaml in the repository root:
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.109.2
hooks:
- id: terraform_fmtCode language: JavaScript (javascript)
Install the Git Hook
pre-commit install
Run the Hook
pre-commit run terraform_fmt --all-files
Test Automatic Formatting
Create an intentionally poorly formatted Terraform file:
variable "environment"{
type=string
default="development"
}Code language: JavaScript (javascript)
Run:
pre-commit run terraform_fmt --all-files
Terraform rewrites it into canonical formatting.
Example:
variable "environment" {
type = string
default = "development"
}Code language: JavaScript (javascript)
If files are modified, pre-commit may report a failure for that run.
Review the changes:
git diff
Stage the corrected files and retry.
When to Use
Enable this hook in practically every Terraform repository.
It is fast, deterministic for a given Terraform version, and prevents formatting-only review comments.
9. Use Case 2: Validate Terraform Configuration
Formatting confirms stylistic consistency.
Validation checks whether a Terraform configuration is internally consistent and satisfies supported Terraform language and provider-schema requirements.
Terraform provides:
terraform validate
However, validation usually requires initialization first.
Step 1: Initialize for Validation
For a root module:
terraform init -backend=falseCode language: JavaScript (javascript)
The -backend=false option is useful for validation without connecting to a configured remote backend.
It does not eliminate all initialization requirements. Terraform may still need to download providers and child modules.
Step 2: Validate
terraform validate
Example successful output:
Success! The configuration is valid.
Configure terraform_validate
Add this hook under the existing pre-commit-terraform repository:
- id: terraform_validate
args:
- --tf-init-args=-backend=false
- --args=-no-color
Run:
pre-commit run terraform_validate --all-files
Why This Matters
The hook helps detect problems such as:
- Invalid Terraform configuration structures.
- Missing required resource arguments.
- Incorrect references.
- Unsupported arguments.
- Certain provider configuration errors.
- Invalid relationships between configuration blocks.
Best Practice
terraform validate is not equivalent to terraform plan.
It does not verify the complete impact of infrastructure changes against real remote infrastructure or state.
Use validation for static correctness and plan for infrastructure-change evaluation.
Recommendation: In large repositories, put validation in the pre-push stage or CI/CD because initialization and provider downloads may be expensive.
10. Use Case 3: Automatically Lint Terraform Using TFLint
Terraform validation does not catch every code-quality or provider-specific issue.
TFLint is designed to complement Terraform validation.
It can identify:
- Deprecated Terraform syntax.
- Unused declarations.
- Undocumented variables or outputs when corresponding rules are enabled.
- Cloud-provider-specific issues.
- Unsupported or suspicious configuration patterns covered by installed rules.
Step 1: Create a TFLint Configuration
Create .tflint.hcl in your repository root.
plugin "terraform" {
enabled = true
preset = "recommended"
}Code language: JavaScript (javascript)
This enables the bundled Terraform language ruleset with its recommended preset.
Step 2: Initialize TFLint
tflint --init
Step 3: Run TFLint Manually
Inside a Terraform directory:
tflint
For a repository containing multiple Terraform directories, use the corresponding hook to select affected directories automatically.
Step 4: Configure the pre-commit Hook
- id: terraform_tflint
args:
- --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
The special placeholder __GIT_WORKING_DIR__ is replaced by the repository root by the pre-commit-terraform hook collection.
This allows multiple Terraform directories to share the same TFLint configuration.
Step 5: Run the Hook
pre-commit run terraform_tflint --all-files
Enable Additional Rules
For example:
- id: terraform_tflint
args:
- --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
- --args=--enable-rule=terraform_documented_variables
This enables the rule checking whether variables are documented.
Cloud-Specific Linting
TFLint can also load provider-specific rulesets for AWS, Azure, and Google Cloud.
These plugins must be configured and installed separately.
For production use, pin reviewed plugin versions, review the applicable rules, and execute tflint --init in an environment where the configuration and plugin sources are available.
When to Use
TFLint is particularly useful for teams maintaining cloud infrastructure across many modules and environments.
It catches issues that Terraform formatting and validation alone may not identify.
11. Use Case 4: Scan Terraform Security Misconfigurations with Trivy
Terraform can create security-sensitive infrastructure resources.
For example:
- Publicly exposed network services.
- Unencrypted storage.
- Broad IAM permissions.
- Insecure database configurations.
- Missing security controls.
- Weak infrastructure defaults.
Trivy provides Infrastructure-as-Code misconfiguration scanning.
Step 1: Test Trivy Manually
Run:
trivy config .
To show only high and critical findings:
trivy config \
--severity HIGH,CRITICAL \
.
To make the command fail when matching findings are detected:
trivy config \
--severity HIGH,CRITICAL \
--exit-code 1 \
.Code language: PHP (php)
The nonzero exit status can be used to block a pipeline or Git hook.
Step 2: Configure terraform_trivy
- id: terraform_trivy
args:
- --args=--severity=HIGH,CRITICAL
- --args=--exit-code=1
Step 3: Run the Hook
pre-commit run terraform_trivy --all-files
Example: Detect Public Exposure
Consider this Terraform resource:
resource "aws_security_group" "example" {
name = "example-security-group"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}Code language: JavaScript (javascript)
This configuration allows SSH access from any IPv4 address.
Trivy can detect such exposures when an enabled rule matches the configuration.
The exact finding, severity, and rule ID depend on the installed Trivy version and its policy database.
When to Use
Security scanning should be mandatory in production Terraform workflows.
For smaller projects, running Trivy locally may be sufficient.
For larger monorepos, put full Trivy scans in pre-push and CI/CD while keeping local commits fast.
12. Use Case 5: Scan Terraform with Checkov
Checkov is another Infrastructure-as-Code scanning tool.
It performs policy and security checks against Terraform and other supported infrastructure configuration formats.
Checkov and Trivy overlap in some capabilities, but their rulesets and reporting workflows differ.
Step 1: Run Checkov Manually
Scan the current directory:
checkov -d .
To scan Terraform specifically:
checkov -d . --framework terraform
Step 2: Configure Checkov with pre-commit
Add the following under the pre-commit-terraform repository:
- id: terraform_checkov
args:
- --args=--quiet
Run:
pre-commit run terraform_checkov --all-files
Step 3: Exclude a Specific Rule When Justified
For example:
- id: terraform_checkov
args:
- --args=--quiet
- --args=--skip-check CKV2_AWS_8
Rule suppression should always have a documented justification and approval process.
Do not disable a security rule simply to make the build green.
Trivy vs. Checkov
| Criteria | Trivy | Checkov |
|---|---|---|
| Terraform misconfiguration scanning | Yes | Yes |
| IaC policy coverage | Yes | Yes |
| Supports additional IaC formats | Yes | Yes |
| CI/CD integration | Yes | Yes |
| Security reporting | Yes | Yes |
| Policy model | Trivy rules and policies | Checkov policies |
| Terraform pre-commit hook | terraform_trivy | terraform_checkov |
For many organizations, one primary scanner with a well-maintained policy baseline is better than enabling multiple scanners without a plan for handling duplicate findings.
Use both where distinct policy coverage justifies the additional complexity.
13. Use Case 6: Automatically Generate Terraform Module Documentation
Terraform modules frequently contain variables, outputs, requirements, and provider details.
Keeping a module’s README synchronized with its configuration can be tedious.
terraform-docs can automatically generate this documentation.
Step 1: Generate Documentation Manually
For a module:
terraform-docs markdown table ./modules/vpc
To write documentation into a README:
terraform-docs markdown table \
--output-file README.md \
--output-mode inject \
./modules/vpc
Step 2: Configure terraform_docs
Add:
- id: terraform_docs
files: ^modules/.*\.tf$
args:
- --hook-config=--add-to-existing-file=true
- --hook-config=--create-file-if-not-exist=true
This scopes documentation generation to Terraform files inside the modules/ directory.
It avoids unexpectedly generating documentation for every environment root module.
Step 3: Add Documentation Markers
In a module’s README:
# VPC Terraform Module
This module creates the required network infrastructure.
## Usage
Add usage examples here.
<!-- BEGIN_TF_DOCS -->
<!-- END_TF_DOCS -->Code language: HTML, XML (xml)
Step 4: Run the Hook
pre-commit run terraform_docs --all-files
The hook updates the generated documentation section.
Step 5: Commit Documentation Changes
Review the changes:
git diff
Stage the module files and updated README:
git add modules/vpc/
Benefits
- Consistent documentation.
- Less manual maintenance.
- Easier module onboarding.
- More complete variable and output documentation.
- Documentation changes reviewed alongside code.
Recommendation: Enable this hook for reusable Terraform modules rather than indiscriminately across every Terraform directory.
14. Use Case 7: Maintain Terraform Provider Lock Files
Terraform uses .terraform.lock.hcl to record selected dependency provider versions and checksums.
This file helps teams use consistent provider versions across development and automation environments.
Step 1: Initialize Terraform
terraform init
Terraform can generate or update .terraform.lock.hcl during initialization.
Step 2: Generate Checksums for Multiple Platforms
For a particular root module:
terraform providers lock \
-platform=darwin_amd64 \
-platform=darwin_arm64 \
-platform=linux_amd64 \
-platform=linux_arm64 \
-platform=windows_amd64
This is useful when developers use macOS or Windows while CI/CD executes on Linux.
Only include platforms required by your organization and supported by the selected providers.
Step 3: Configure the Provider Lock Hook
Optional hook:
- id: terraform_providers_lock
args:
- --hook-config=--mode=regenerate-lockfile-if-some-platform-missed
- --args=-platform=darwin_arm64
- --args=-platform=linux_amd64
- --args=-platform=windows_amd64
Run:
pre-commit run terraform_providers_lock --all-files
Important Considerations
- Provider lock operations may require network access.
- Lockfile regeneration can be slow.
- Some providers do not support every platform.
- Lockfiles should normally be committed for root configurations.
- Do not blindly update providers on every commit.
- Private provider registries may require authentication.
The provider-lock hook is optional. Many teams prefer explicit lockfile maintenance during dependency upgrades rather than running it automatically on every commit.
15. Use Case 8: Detect Private Keys and Common File Problems
Terraform repositories can contain files such as:
variables.tf
terraform.tfvars.example
backend.hcl
provider.tfCode language: CSS (css)
While infrastructure parameters often belong in version control, credentials and local state files usually do not.
Add the standard pre-commit hooks collection:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-merge-conflict
- id: detect-private-key
- id: check-added-large-files
args: [--maxkb=1024]
These hooks provide additional file hygiene and basic safety checks.
Test Private-Key Detection
pre-commit run detect-private-key --all-filesCode language: PHP (php)
Validate YAML Configuration
pre-commit run check-yaml --all-files
Check for Merge Conflicts
pre-commit run check-merge-conflict --all-files
Recommended Terraform .gitignore
# Terraform working directories
**/.terraform/*
# Local Terraform state files
*.tfstate
*.tfstate.*
# Terraform crash logs
crash.log
crash.*.log
# Saved plan artifacts
*.tfplan
tfplan
tfplan.*
# Local overrides
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Sensitive local variable files
*.auto.tfvars
*.auto.tfvars.json
# Local credentials
.env
.env.*
!.env.example
# Terraform CLI configuration
.terraformrc
terraform.rcCode language: PHP (php)
Do not ignore .terraform.lock.hcl for normal root-module workflows where provider dependency locking is required.
Also, do not assume .gitignore prevents secret leakage. It does not remove files already tracked by Git, and Terraform state may contain sensitive data.
Use secret scanning and appropriate state-storage security controls in addition to Git hooks.
16. Use Case 9: Separate Fast and Slow Hooks
A common mistake is enabling every hook during git commit.
This can make commits frustratingly slow.
A better approach is to separate quick checks from resource-intensive checks.
Fast Checks โ Pre-commit
terraform_fmt
terraform_tflint
terraform_docs
trailing-whitespace
end-of-file-fixer
check-yaml
detect-private-keyCode language: PHP (php)
Heavier Checks โ Pre-push
terraform_validate
terraform_trivy
Additional complete scans and policy gates can run in CI/CD.
Configure Git Hook Stages
For example:
default_install_hook_types:
- pre-commit
- pre-push
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.109.2
hooks:
- id: terraform_fmt
stages: [pre-commit]
- id: terraform_validate
stages: [pre-push]
args:
- --tf-init-args=-backend=false
- id: terraform_trivy
stages: [pre-push]Code language: JavaScript (javascript)
Install both hook launchers:
pre-commit install \
--hook-type pre-commit \
--hook-type pre-push
Run Pre-commit Stage Manually
pre-commit run --all-files --hook-stage pre-commit
Run Pre-push Stage Manually
pre-commit run --all-files --hook-stage pre-push
Benefits
This approach keeps routine commits fast while still checking more expensive conditions before code is pushed.
However, developers can bypass local hooks. Required CI/CD checks remain essential.
17. Use Case 10: Configure pre-commit for Terraform Monorepos
Terraform monorepos commonly contain many independent working directories.
For example:
infrastructure/
โโโ modules/
โ โโโ vpc/
โ โโโ eks/
โโโ environments/
โ โโโ development/
โ โโโ staging/
โ โโโ production/
โโโ .pre-commit-config.yaml
Each environment may use different:
- Providers.
- Provider versions.
- Backend configurations.
- Modules.
- Credentials.
- Terraform CLI versions.
Terraform operations are normally scoped to working directories, whereas pre-commit selects files.
The pre-commit-terraform hooks handle much of the working-directory selection automatically.
Run Checks Only for Development
pre-commit run \
--files environments/development/main.tf
Run Checks Only for Production
pre-commit run \
--files environments/production/main.tf
The relevant hooks determine the Terraform working directories based on the files supplied.
Limit Security Scans to Production
Example:
- id: terraform_trivy
files: ^environments/production/.*\.tf$
Exclude Generated Files
At the top of .pre-commit-config.yaml:
exclude: |
(?x)^(
\.terraform/|
.*/\.terraform/|
generated/|
vendor/
)Code language: JavaScript (javascript)
Important Limitation
pre-commit is file-oriented.
If the only change in a directory is deletion of a Terraform file, directory-oriented checks may be skipped because no remaining matching file is passed to the hook.
For that reason, CI/CD should also run complete validation for critical Terraform working directories.
18. Use Case 11: Scan Terraform Infrastructure Cost
Infrastructure cost awareness can be incorporated into Terraform development using Infracost.
Infracost estimates costs for supported Terraform resources.
Install Infracost
Follow:
Authenticate using an appropriately scoped Infracost API key.
Run Manually
For an example root module:
infracost breakdown \
--path environments/development
Add the Hook
- id: infracost_breakdown
args:
- --args=--path=environments/development
The hook can evaluate estimated infrastructure costs according to the configured Infracost settings.
The hook also supports jq-compatible cost conditions.
Recommended Usage
Cost analysis is usually better suited to CI/CD or pull-request reporting than every local commit.
Cost estimation may require remote API access, consumes additional time, and does not cover every Terraform resource.
19. Use Case 12: Configure Terraform pre-commit for Terragrunt
Terragrunt projects use additional HCL configuration.
The pre-commit-terraform repository provides hooks such as:
terragrunt_fmt
terragrunt_validate
terragrunt_validate_inputs
terragrunt_providers_lock
Example:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.109.2
hooks:
- id: terragrunt_fmt
- id: terragrunt_validate
- id: terragrunt_validate_inputs
These hooks require a compatible Terragrunt installation and may need access to providers, modules, or cloud authentication.
For large Terragrunt deployments, start with formatting and add validation in a controlled stage after testing initialization and dependency behavior.
20. Use Case 13: Support OpenTofu with pre-commit
The community hook collection also supports OpenTofu.
If you use OpenTofu instead of Terraform, you can explicitly configure the hook to use it.
Example:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.109.2
hooks:
- id: terraform_fmt
args:
- --hook-config=--tf-path=opentofu
- id: terraform_validate
args:
- --hook-config=--tf-path=opentofu
Ensure OpenTofu is installed and accessible.
You can verify it using:
tofu version
The hook’s --tf-path=opentofu setting explicitly selects OpenTofu through the hook collection’s supported tool-resolution mechanism.
Do not assume Terraform and OpenTofu versions are interchangeable. Test formatting, validation, and provider compatibility against the versions your organization actually uses.
21. Use Case 14: Automate Terraform Quality Checks in GitHub Actions
Local Git hooks alone do not guarantee quality.
Developers can skip hooks, and automated changes may bypass local workstation controls entirely.
CI/CD provides centrally executed checks.
Create a Workflow
Create:
.github/workflows/terraform-quality.yml
For a basic Terraform formatting and validation workflow:
name: Terraform Quality Checks
on:
pull_request:
push:
branches:
- main
permissions:
contents: read
jobs:
terraform-quality:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Setup Terraform
uses: hashicorp/setup-terraform@v4
with:
terraform_version: "1.14.6"
terraform_wrapper: false
- name: Install pre-commit
run: |
python -m pip install pre-commit==4.7.0
- name: Validate pre-commit Configuration
run: |
pre-commit validate-config
- name: Check Terraform Formatting
run: |
pre-commit run terraform_fmt --all-files
- name: Validate Terraform
run: |
pre-commit run terraform_validate \
--all-files \
--hook-stage pre-pushCode language: JavaScript (javascript)
This example assumes the corresponding hooks are present in .pre-commit-config.yaml and that validation does not require unavailable private credentials.
It is a basic pipeline, not a complete installation of every optional scanner in this article.
To enforce TFLint, Trivy, Checkov, or terraform-docs in GitHub Actions, install the corresponding tools or use an approved, pinned container image containing them.
Complete Hook Execution Using a Docker Image
The pre-commit-terraform project publishes an image containing Terraform-related tooling.
An example CI/CD job can run:
name: Terraform Complete Checks
on:
pull_request:
permissions:
contents: read
jobs:
terraform-checks:
runs-on: ubuntu-latest
container:
image: ghcr.io/antonbabenko/pre-commit-terraform:latest
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Validate Configuration
run: pre-commit validate-config
- name: Run Pre-commit Checks
run: |
pre-commit run \
--all-files \
--hook-stage pre-commit
- name: Run Pre-push Checks
run: |
pre-commit run \
--all-files \
--hook-stage pre-pushCode language: HTTP (http)
Production warning: The latest tag above is illustrative. Pin a verified image digest or reviewed version for real CI/CD pipelines. Review the image’s included tool versions, dependencies, security posture, and access to private Terraform modules.
CI should fail when a hook finds a policy violation or modifies a file that should already have been formatted.
Do not automatically commit hook-generated changes from untrusted pull-request workflows.
22. Use Case 15: Enforce Terraform pre-commit Across a Team
An effective team rollout requires more than creating a YAML file.
The repository configuration should be version-controlled and referenced in the developer onboarding process.
Step 1: Commit the Configuration
git add .pre-commit-config.yaml
git commit -m "Add Terraform pre-commit hooks"Code language: CSS (css)
Step 2: Every Developer Installs the Hook
After cloning the repository:
pre-commit install \
--hook-type pre-commit \
--hook-type pre-push
Step 3: Initialize Hook Environments
pre-commit install-hooks
Step 4: Validate the Complete Repository
pre-commit run --all-files --hook-stage pre-commit
pre-commit run --all-files --hook-stage pre-push
Step 5: Enforce Quality in CI/CD
Add required CI checks to your repository’s branch protection or rulesets.
For critical infrastructure repositories, a useful quality policy is:
| Control | Local | CI/CD |
|---|---|---|
| Terraform formatting | Required | Required |
| Terraform linting | Recommended | Required |
| Terraform validation | Pre-push | Required |
| Terraform security scanning | Recommended | Required |
| Terraform documentation | Required for modules | Verified |
| Provider lock consistency | When changed | Verified |
| Terraform plan | Optional for local testing | Required before deployment |
| Code review | Pull request | Required |
| Terraform apply | No automatic commit-time apply | Separate authorized deployment |
Never make infrastructure-changing operations such as terraform apply part of a standard pre-commit hook.
23. Complete Production-Ready .pre-commit-config.yaml
The following is a recommended starting configuration for a Terraform repository with reusable modules and multiple environments.
It combines formatting, file hygiene, linting, module documentation, validation, and security scanning.
File: .pre-commit-config.yaml
# Terraform pre-commit configuration
minimum_pre_commit_version: "4.0.0"
default_install_hook_types:
- pre-commit
- pre-push
exclude: |
(?x)^(
\.terraform/|
.*/\.terraform/|
generated/|
vendor/
)
repos:
# General file hygiene
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
stages: [pre-commit]
- id: end-of-file-fixer
stages: [pre-commit]
- id: check-yaml
stages: [pre-commit]
- id: check-json
stages: [pre-commit]
- id: check-merge-conflict
stages: [pre-commit]
- id: detect-private-key
stages: [pre-commit]
- id: check-added-large-files
stages: [pre-commit]
args:
- --maxkb=1024
# Terraform-specific checks
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.109.2
hooks:
# 1. Terraform formatting
- id: terraform_fmt
stages: [pre-commit]
# 2. Terraform linting
- id: terraform_tflint
stages: [pre-commit]
args:
- --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
# 3. Terraform module documentation
- id: terraform_docs
stages: [pre-commit]
files: ^modules/.*\.tf$
args:
- --hook-config=--add-to-existing-file=true
- --hook-config=--create-file-if-not-exist=true
# 4. Terraform validation
- id: terraform_validate
stages: [pre-push]
args:
- --tf-init-args=-backend=false
- --args=-no-color
- --hook-config=--parallelism-limit=1
# 5. Terraform security scanning
- id: terraform_trivy
stages: [pre-push]
args:
- --args=--severity=HIGH,CRITICAL
- --args=--exit-code=1Code language: PHP (php)
Additional .tflint.hcl
Create a file named .tflint.hcl in the repository root:
plugin "terraform" {
enabled = true
preset = "recommended"
}Code language: JavaScript (javascript)
Activate the Configuration
Run:
pre-commit validate-config
Install the hooks:
pre-commit install \
--hook-type pre-commit \
--hook-type pre-push
Prepare hook environments:
pre-commit install-hooks
Run quick checks:
pre-commit run --all-files --hook-stage pre-commit
Run heavier checks:
pre-commit run --all-files --hook-stage pre-push
Important Setup Notes
This full configuration assumes that Terraform, TFLint, terraform-docs, and Trivy are installed and accessible.
The shared .tflint.hcl example must exist before enabling the TFLint hook.
The terraform_docs hook assumes reusable modules are stored under modules/. Change or remove that path filter for different repository structures.
The validation hook uses Terraform initialization without a backend. This is appropriate for many repositories, but remote module dependencies and private registries may still require authentication.
Finally, run the full configuration against a representative repository and review the output before enforcing it across a team.
24. Terraform pre-commit Command Cheat Sheet
| Use case | Command |
|---|---|
| Check pre-commit version | pre-commit --version |
| Validate hook configuration | pre-commit validate-config |
| Install default hook | pre-commit install |
| Prepare hook environments | pre-commit install-hooks |
| Run configured pre-commit hooks | pre-commit run |
| Run all pre-commit hooks against tracked files | pre-commit run --all-files |
| Run pre-push-stage hooks | pre-commit run --all-files --hook-stage pre-push |
| Format Terraform | terraform fmt -recursive |
| Check Terraform formatting | terraform fmt -check -recursive |
| Run terraform_fmt hook | pre-commit run terraform_fmt --all-files |
| Validate Terraform manually | terraform validate |
| Run Terraform validation hook | pre-commit run terraform_validate --all-files |
| Run TFLint | tflint |
| Run TFLint hook | pre-commit run terraform_tflint --all-files |
| Run Trivy | trivy config . |
| Run Trivy hook | pre-commit run terraform_trivy --all-files |
| Run Checkov | checkov -d . --framework terraform |
| Run Checkov hook | pre-commit run terraform_checkov --all-files |
| Generate module documentation | terraform-docs markdown table ./modules/vpc |
| Run terraform_docs hook | pre-commit run terraform_docs --all-files |
| Update hook revisions | pre-commit autoupdate |
| Clear cached hook environments | pre-commit clean |
| Remove hooks | pre-commit uninstall |
For hooks configured exclusively for the pre-push stage, explicitly add --hook-stage pre-push when running them manually.
25. Troubleshooting Terraform pre-commit Problems
Error 1: terraform: command not found
Possible cause: Terraform is not installed or is missing from PATH.
Verify:
terraform version
Find the executable:
command -v terraform
Install the compatible Terraform version required by the project.
Error 2: terraform_fmt Modified Files
Example:
Terraform fmt........................Failed
- files were modified by this hookCode language: JavaScript (javascript)
This usually indicates that formatting corrections were applied.
Review:
git diff
Stage the corrected files and rerun the hook.
Error 3: terraform_validate Fails During Initialization
Possible causes:
- Required provider or module cannot be downloaded.
- Private module authentication is missing.
- Terraform or provider version mismatch.
- Invalid dependency lock file.
- Unsupported initialization or backend configuration.
Run the commands manually in the failing working directory:
terraform init -backend=false
terraform validateCode language: JavaScript (javascript)
Review the actual error message before changing the hook configuration.
Error 4: TFLint Plugin Initialization Failed
Try:
tflint --init
Review .tflint.hcl and any configured external plugins.
Confirm the selected plugin version is compatible with the installed TFLint version.
Error 5: Trivy Reports Security Violations
Run:
trivy config .
Inspect each finding and determine whether it represents a real security risk.
Correct the Terraform configuration or document a justified, approved exception.
Avoid suppressing rules globally merely to allow the pipeline to pass.
Error 6: terraform-docs Modified README.md
This is expected when generated documentation needs updating.
Review:
git diff
Stage the README changes alongside the Terraform code.
Error 7: Hooks Are Very Slow
Possible causes include provider downloads, private module initialization, large security scans, or too many Terraform directories.
Consider:
- Moving validation to pre-push or CI/CD.
- Using provider/plugin caches carefully.
- Limiting parallelism for conflicting initialization workloads.
- Scoping hooks to relevant directories.
- Avoiding unnecessary provider upgrades.
- Pinning tool versions.
- Splitting large monorepo checks into independent CI jobs.
The hook collection supports options such as:
args:
- --hook-config=--parallelism-limit=1
This can be particularly useful when Terraform validation shares plugin caches or accesses constrained private registries.
Error 8: Windows Hook Fails with Bash Error
The Terraform hook collection relies on Bash.
Use WSL2 or Docker when Windows shell compatibility becomes problematic.
Verify Bash availability:
bash --version
For native Windows setups, be aware that different installations of Bash can produce incompatible behavior.
Error 9: No Terraform Files Found
pre-commit runs hooks only when the hook’s file filters match relevant files.
Check:
git status
Inspect which files are tracked:
git ls-files
Then run:
pre-commit run terraform_fmt --all-files --verbose
A hook reporting Skipped can be normal when no applicable files exist.
26. Terraform pre-commit Best Practices for Production
A mature Terraform workflow should balance reliability, security, and developer experience.
1. Always Enable Terraform Formatting
Make terraform_fmt mandatory in all Terraform repositories.
2. Use TFLint for Additional Code Quality
Terraform validation and TFLint complement each other.
3. Run Security Scans Before Merging
Use Trivy, Checkov, or another approved IaC scanning tool.
4. Avoid Expensive Operations During Every Commit
Keep the pre-commit stage fast.
Move expensive operations to pre-push or CI/CD.
5. Keep Module Documentation Updated
Use terraform-docs for reusable modules.
6. Maintain Provider Lock Files
Commit appropriate .terraform.lock.hcl files for root modules.
Review provider version changes deliberately.
7. Never Run terraform apply in pre-commit
A Git commit must not unexpectedly create, change, or destroy infrastructure.
8. Enforce CI/CD Checks
Local hooks can be skipped, so CI must independently run required validations.
9. Pin Versions
Pin the pre-commit framework, hook repositories, Terraform CLI, TFLint, scanner versions, and relevant CI dependencies.
10. Minimize Permissions
Formatting and validation should not require highly privileged production credentials.
11. Avoid Secrets in Terraform Repositories
Protect local variable files, state files, credentials, and backend configurations.
Use secure credential delivery and dedicated secrets management.
12. Keep Terraform Plans Separate
Terraform plan may require access to remote state, cloud APIs, and sensitive variables.
Execute plans in an appropriately controlled environment.
13. Configure Environment Isolation
Use separate credentials and appropriate access controls for development, staging, and production.
14. Review Hook Upgrades
Run:
pre-commit autoupdate
Then review the dependency changes and rerun all checks before committing them.
15. Optimize Before Enforcing
Measure how long hooks take across representative modules before making them mandatory for every developer.
27. Frequently Asked Questions
Q1. Is pre-commit mandatory for Terraform?
No. Terraform works without pre-commit.
However, pre-commit can improve consistency and catch common errors earlier.
Q2. Should terraform fmt run before terraform validate?
Yes. Formatting is typically faster, so it is efficient to run formatting before more expensive validation.
Q3. Is terraform validate enough for Terraform security?
No. Terraform validation checks configuration correctness, not comprehensive security compliance.
Use security scanners and appropriate policy controls.
Q4. Which is better for Terraform: Checkov or Trivy?
Both support Terraform misconfiguration scanning.
Choose based on policy coverage, existing integrations, reporting requirements, and your team’s security standards.
Q5. Should TFLint run on every commit?
For smaller repositories, yes, if execution remains fast.
For large monorepos, selective execution or CI-based linting may improve developer experience.
Q6. Should terraform-docs run automatically?
Yes, particularly for reusable Terraform modules.
It helps keep documentation aligned with code.
Q7. Can pre-commit work with HCP Terraform or Terraform Cloud?
Yes.
However, local validation, private module downloads, and remote execution workflows may have different authentication and initialization requirements.
Avoid configuring ordinary developer hooks to depend on privileged production credentials.
Q8. Can pre-commit work with Terraform modules stored in private Git repositories?
Yes, provided the environment can authenticate to those repositories.
Hooks that initialize Terraform may need access to the private module sources.
Q9. Can pre-commit be used in a Terraform monorepo?
Yes.
The Terraform hook collection supports directory-aware operations, and pre-commit supports file filters and exclusions.
For deleted-file-only changes or cross-directory dependencies, supplement file-based checks with CI validation.
Q10. Does pre-commit automatically fix Terraform security issues?
Formatting and documentation hooks may automatically modify files.
Security scanners typically report problems rather than safely rewriting infrastructure.
Security findings usually require deliberate review and changes.
28. Final Recommended Terraform Quality Workflow
For most professional Terraform teams, the following staged workflow is a strong starting point.
| Check | Pre-commit | Pre-push | CI/CD |
|---|---|---|---|
| Terraform formatting | Yes | โ | Yes |
| Whitespace/file checks | Yes | โ | Yes |
| YAML/JSON validation | Yes | โ | Yes |
| TFLint | Yes | Optional | Yes |
| terraform-docs | Yes | โ | Yes |
| Terraform validate | โ | Yes | Yes |
| Trivy | โ | Yes | Yes |
| Checkov | โ | Optional | Optional |
| Provider lock checks | On dependency change | Optional | Yes |
| Infracost | โ | โ | Optional |
| Terraform plan | โ | โ | Yes |
| Terraform apply | Never | Never | Approved deployment only |
The exact gates should reflect repository size, team requirements, security policy, and infrastructure criticality.
Conclusion
pre-commit can make Terraform development more consistent by automatically running formatting, validation, linting, documentation, and security checks before infrastructure code is merged.
The most important hooks are:
terraform_fmt
terraform_validate
terraform_tflint
terraform_trivy
terraform_docs
Additional hooks for Checkov, provider locks, cost estimation, and Terragrunt can be introduced when required.
A practical rollout begins with formatting and linting, adds validation and security scanning, and then enforces the same standards through CI/CD.
With the right configuration, Terraform teams can reduce avoidable mistakes, improve code reviews, strengthen security practices, and maintain more reliable infrastructure repositories without unnecessarily slowing down daily development.
Official Documentation and References
- pre-commit Official Documentation
- pre-commit Releases
- pre-commit-terraform Repository
- pre-commit-terraform Releases
- Official pre-commit Hooks
- Terraform CLI Documentation
- Terraform Validation Documentation
- TFLint Repository
- terraform-docs Documentation
- Trivy Documentation
- Checkov Repository
- Infracost Documentation
- GitHub Actions Documentation
Last reviewed: October 20, 2026. Hook behavior, command-line options, tool releases, and integration requirements may change. Validate the complete configuration against a representative project before enforcing it in production.
I’m Rajesh Kumar, a DevOps, SRE, DevSecOps, Cloud, and Platform Engineering expert passionate about sharing practical knowledge, real-world experiences, and industry best practices. I have worked at Cotocus and regularly write about technology, travel, investing, health, product reviews, and digital marketing through my various platforms.
I publish technical articles at DevOps School, travel stories at Holiday Landmark, stock market insights at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at TrueReviewNow, and SEO and digital marketing strategies at Wizbrand.
Find Trusted Cardiac Hospitals
Compare heart hospitals by city and services โ all in one place.
Explore Hospitals