Skip to content

Terraform GitHub repo structureΒΆ

Keeping track of Terraform code can be challengingβ€”especially when working across different systems, in VSCode, or through platforms like Terraform Cloud. My preferred approach is to centralize all Terraform code in one place and reference it from various systems when needed. This ensures consistent infrastructure builds by using the same module code across environments.

By organizing my code this way, I can:

  • βœ… Maintain uniformity across deployments
  • πŸ”– Version my modules effectively
  • πŸ€– Automate workflows with GitHub Actions
  • πŸ›‘οΈ Scan for security vulnerabilities
  • πŸ“š Generate and maintain documentation

βš™οΈ Code sequenceΒΆ

Resource Module Repo (Account 1)ΒΆ

  • Contains multiple repositories.
  • Each repo holds Terraform modules for a specific Azure resource (e.g., storage, VM, network).
  • Modules are designed to be reused via HTTPS links.

Deployment Repo (Account 2)ΒΆ

  • Contains multiple repositories, each tied to a specific Azure subscription.
  • Inside each repo, users create subfolders for individual deployments.

Step-by-Step WorkflowΒΆ

  1. User creates a new subfolder in the deployment subscription repo for.
  2. Inside the subfolder, user writes Terraform .tf files for the resources they want to deploy.
  3. In those .tf files, user references resource modules via HTTPS from the module repo.
  4. User commits and pushes the deployment code.
  5. A GitHub Actions workflow runs the deployment.
  6. Terraform pulls the modules and provisions resources in Azure.
  7. Azure confirms successful deployment of resources.
sequenceDiagram
  autonumber
  participant User
  participant AzureRepo as Azure Subscription Repo
  participant ModuleRepo as Terraform Module Repo

  User->>AzureRepo: Create new subfolder for deployment
  AzureRepo->>User: Scaffold resource-specific .tf files
  User->>ModuleRepo: Reference reusable module via HTTPS
  ModuleRepo-->>User: Provide module logic (e.g., storage, VM, etc.)
  User->>AzureRepo: Commit and push deployment code
  AzureRepo->>Terraform: Trigger deployment (via pipeline or CLI)
  Terraform->>Azure: Provision resources using modules
  Azure-->>User: Resources deployed successfully

πŸ—‚οΈ Resource Module RepositoryΒΆ

Terraform code for Azure and AWS resources is stored in a dedicated GitHub account. Instead of nesting modules within subfolders, each reusable module is maintained in its own repositoryβ€”organized by resource type. This structure enhances discoverability and simplifies management, allowing modules to be referenced directly via HTTPS and version tags.

Naming ConventionΒΆ

Repositories follow a consistent naming pattern:

Azure: terraform-azurerm-{resource}

AWS: terraform-aws-{resource}

This convention aligns with Terraform Cloud registry standards and streamlines module imports.

Example Repository LayoutΒΆ

Below is an example structure for a typical Azure module repository:

acme-terraform-modules-azure             / GitHub Account
└── terraform-azurerm-resource_group     / Repository for Azure Resource Group module
    β”œβ”€β”€ .github/
    β”‚   └── workflows/
    β”‚       └── ci-terraform.yaml        / CI pipeline for Terraform
    β”œβ”€β”€ ExampleConfiguration/            / Sample deployment configuration
    β”‚   β”œβ”€β”€ main.tf
    └── checkov-security-scan/           / Security scan results
        └── results_cli.txt
    β”œβ”€β”€ main.tf                          / Core resource definitions
    β”œβ”€β”€ CHANGELOG.md                     / Version history
    β”œβ”€β”€ LICENSE                          / Licensing information
    β”œβ”€β”€ .gitignore                       / Git exclusions
    β”œβ”€β”€ README.md                        / Module documentation

πŸ—‚οΈ Deployment Module RepositoryΒΆ

I store Terraform code for Azure and AWS resources in a dedicated GitHub account. Rather than nesting modules in subfolders, each reusable module lives in its own repositoryβ€”organized by resource type. This makes management and discovery easier as you can reference the repository directly using https and the tag version.

Example Repository LayoutΒΆ

This is an example layout for a typical Azure module repository. The GitHub account serves as a central hub, while individual repositories are aligned with specific Azure subscriptions. This separation enables distinct authentication credentials between GitHub and each Azure subscription, reducing the overall security exposure.

Within each subscription-specific repository, folders represent individual deployments. Each folder contains resource configuration files for a particular applicationβ€”similar to how Azure resource groups organize resources for a specific deployment.

acme-terraform-deployments-azure      / GitHub Account
└── azure-subscription-00             / Repository for a specific Azure subscription
    β”œβ”€β”€ .github/
    β”‚   β”œβ”€β”€ actions/                  / Custom GitHub Actions
    β”‚   β”œβ”€β”€ workflows/                / Workflow definitions triggering actions
    β”œβ”€β”€ deployment01/                 / First deployment folder
    β”‚   β”œβ”€β”€ resource-group.tf         / Defines resource group
    β”‚   β”œβ”€β”€ storage-account.tf        / Defines storage account
    β”œβ”€β”€ deployment02/                 / Second deployment folder
    β”‚   β”œβ”€β”€ resource-group.tf         / Defines resource group
    β”‚   β”œβ”€β”€ key-vault.tf              / Defines Key Vault
    β”‚   β”œβ”€β”€ azure-sql-database.tf     / Defines Azure SQL Database    
    β”œβ”€β”€ .gitignore                    / Files and folders to exclude from Git
    β”œβ”€β”€ README.md                     / Documentation for the module

βœ… Best PracticesΒΆ

To maintain clean, scalable, and reliable infrastructure code, I follow these core principles:

  • Consistent Naming Adopt predictable, registry-compliant naming conventions to simplify module discovery and imports.
  • Version Control Use semantic versioning to track changes and manage releases, ensuring stability and traceability across environments.
  • Automation Implement CI/CD pipelines to streamline deployments, enforce coding standards, and minimize manual intervention.
  • Security First Integrate tools like Checkov to proactively detect misconfigurations and enforce security policies during development.