Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save zidenis/93f8f93429e443c72243889b18bccad1 to your computer and use it in GitHub Desktop.

Select an option

Save zidenis/93f8f93429e443c72243889b18bccad1 to your computer and use it in GitHub Desktop.
A step-by-step guide to setting up a complete Terraform development environment

Terraform cookbook : development environment setup

A recipe to set up a good development environment to write terraform modules. Tested with Linux Ubuntu 24.04.1 LTS on WSL2 (should work with other Linux distros with some minor adaptations).

Ingredients:

Preparation Steps:

1. Install tenv: a version manager for Terraform (also for OpenTofu, Terragrunt and Atmos).

Simplifies the management of multiple Terraform versions, ensuring compatibility with different projects.

TENV_LATEST=$(curl -s https://api.github.com/repos/tofuutils/tenv/releases/latest | jq -r '.assets[] | select(.name | endswith("Linux_x86_64.tar.gz")) | .browser_download_url')

curl -L -O $TENV_LATEST

mkdir ~/.tenv

tar xvzf $(echo $TENV_LATEST | grep -o -E "tenv_v.*") -C ~/.tenv

export PATH="$HOME/.tenv:$PATH"

tenv completion bash > ~/.tenv/tenv_completion.bash

echo -e '\n# tenv and terraform tools\nexport PATH="$HOME/.tenv:$PATH"\nsource $HOME/.tenv/tenv_completion.bash' >> ~/.bashrc

2. Install terraform CLI using tenv.

tenv terraform install

terraform -install-autocomplete

3. Install terraform-docs: a tool to generate documentation from Terraform modules.

Automates the creation of files documenting inputs, outputs, resources, and dependencies in a Terraform module.

TDOC_LATEST=$(curl -s https://api.github.com/repos/terraform-docs/terraform-docs/releases/latest | jq -r '.assets[] | select(.name | endswith("linux-amd64.tar.gz")) | .browser_download_url')

curl -L -O $TDOC_LATEST

tar xzf $(echo $TDOC_LATEST | grep -o -E "terraform-docs-.+") -C ~/.tenv terraform-docs

terraform-docs completion bash > ~/.tenv/terraform-docs_completion.bash

echo -e '\nsource $HOME/.tenv/terraform-docs_completion.bash' >> ~/.bashrc

4. Install TFLint: a linter for Terraform code.

Ensures best practices, identifies syntax errors, and enforces standards for Terraform configurations.

TFLINT_LATEST=$(curl -s https://api.github.com/repos/terraform-linters/tflint/releases/latest | jq -r '.assets[] | select(.name | endswith("tflint_linux_amd64.zip")) | .browser_download_url')

curl -L -O $TFLINT_LATEST

unzip -o $(echo $TFLINT_LATEST | grep -o -E "tflint_linux.+") -d ~/.tenv

5. Install Trivy: a comprehensive and versatile security scanner.

Identifies security risks in container images, IaC files (including Terraform), and dependencies.

TRIVY_LATEST=$(curl -s https://api.github.com/repos/aquasecurity/trivy/releases/latest | jq -r '.assets[] | select(.name | endswith("Linux-64bit.tar.gz")) | .browser_download_url')

curl -L -O $TRIVY_LATEST

tar xzf $(echo $TRIVY_LATEST | grep -o -E "trivy_.+") -C ~/.tenv trivy

6. Install pre-commit: A framework for managing and maintaining Git hooks.

Ensures consistent code quality by running checks (e.g., linting, formatting, security scans) before committing code to a repository.

sudo apt install python3.12-venv

python3 -m venv ~/.venv

source ~/.venv/bin/activate

pip install pre-commit

7. Install Checkov: a static code analysis tool for IaC.

Detects misconfigurations, security risks, and compliance violations in Terraform and other IaC templates.

pip install checkov

8. Setup VSCode with a terraform extension.

To develop terraform modules I use VSCode with Terraform extension by Anton Kulikov. It adds syntax support for the Terraform and Terragrunt configuration language.

9. Setup the terraform root module directory.

Now that you installed all the devlopment supporting tools, its time to configure the terraform root module directory structure. A Standard Module Structure is presented in https://developer.hashicorp.com/terraform/language/modules/develop/structure . Look at the example bellow.

root-module/
├── README.md
├── main.tf
├── variables.tf
├── outputs.tf
├── providers.tf
├── modules/
│   ├── child-module-A/
│   │   ├── README.md
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   ├── child-module-B/
│   ├── .../
├── .pre-commit-config.yaml
└── .tflint.hcl

The .tflint.hcl file is the configuration file for TFLint. Its purpose is to define the rules, plugins, and configurations that TFLint will use when analyzing your Terraform code. This allows you to enforce best practices, identify issues, and customize the linter's behavior to fit your project requirements. The config that I use for terraform AWS resources is:

tflint {
  required_version = "~> 0.54.0"
}

plugin "terraform" {
  enabled = true
  preset  = "all"
}

plugin "aws" {
  enabled = true
  version = "0.36.0"
  source  = "github.com/terraform-linters/tflint-ruleset-aws"
  deep_check = true
}

rule "aws_resource_missing_tags" {
  enabled = true
  tags = [
    "env"
  ]
}

The .pre-commit-config.yaml file is the configuration file for the Pre-commit framework. Its purpose is to define and manage pre-commit hooks, which are scripts that run automatically before a commit is made in a Git repository. These hooks ensure that code quality, consistency, and compliance checks are enforced.

repos:
  - repo: https://github.com/antonbabenko/pre-commit-terraform
    rev: v1.96.2
    hooks:
      - id: terraform_validate
      - id: terraform_fmt
      - id: terraform_tflint
        args:
          - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
      - id: terraform_trivy
      - id: terraform_checkov
        name: "Terraform validate with Checkov"
        args:
          - --args=--quiet
      - id: terraform_docs

  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: detect-aws-credentials
        name: "Pre-commit detect AWS credentials"
      - id: detect-private-key
        name: "Pre-commit detect private keys"
      - id: end-of-file-fixer
        name: "Pre-commit fix end of files"
      - id: trailing-whitespace
        name: "Pre-commit remove trailing whitespaces"

Bonus: A Terraform Module Template for AWS Resources

This template serves as a foundation for creating Terraform modules.

I developed a template to bootstrap the development of terraform modules to provision AWS resources. It help me to create an S3 bucket to store terraform state (with server-side encryption, versioning, lifecycle rules for noncurrent object transition and expiration, blocked of public access for enhanced security), and also creates a DynamoDB table for state locking.

Usage

# Use AWS CLI to configure the AWS Access Key ID and the AWS Secret Access Key for the user with the propper permission to provision the AWS resources. 
aws configure

git clone https://github.com/zidenis/terraform-module-template-aws.git my-terraform-module

cd my-terraform-module

git remote remove origin

# Use this bash script to bootstrap the S3 bucket to hold the terraform state remotely
./backend_bootstrap.sh

Now the infrastructure is ready to start the development of your module. Use pre-commit to run the quality validations.

$ source ~/.venv/bin/activate

$ pre-commit run -a
[INFO] Initializing environment for https://github.com/antonbabenko/pre-commit-terraform.
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
Terraform validate.......................................................Passed
Terraform fmt............................................................Passed
Terraform validate with tflint...........................................Passed
Terraform validate with trivy............................................Passed
Terraform validate with Checkov..........................................Passed
Terraform docs...........................................................Passed
Pre-commit detect AWS credentials........................................Passed
Pre-commit detect private keys...........................................Passed
Pre-commit fix end of files..............................................Passed
Pre-commit remove trailing whitespaces...................................Passed

Cleanup

rm $(echo $TENV_LATEST | grep -o -E "terraform-docs-.+")
rm $(echo $TENV_LATEST | grep -o -E "tenv_v.*")
rm $(echo $TFLINT_LATEST | grep -o -E "tflint_linux.+")
rm $(echo $TRIVY_LATEST | grep -o -E "trivy_.+")

Tools versions at the moment of the write up

$ tenv version
tenv version v3.2.11

$ terraform version
Terraform v1.10.2
on linux_amd64

$ terraform-docs version
terraform-docs version v0.19.0 af31cc6 linux/amd64

$ tflint --version
TFLint version 0.54.0
+ ruleset.terraform (0.10.0-bundled)

$ trivy --version
Version: 0.58.0

$ pre-commit --version
pre-commit 4.0.1

$ checkov --version
3.2.334
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment