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ΒΆ
- User creates a new subfolder in the deployment subscription repo for.
- Inside the subfolder, user writes Terraform .tf files for the resources they want to deploy.
- In those .tf files, user references resource modules via HTTPS from the module repo.
- User commits and pushes the deployment code.
- A GitHub Actions workflow runs the deployment.
- Terraform pulls the modules and provisions resources in Azure.
- 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.