An Azure Landing Zone is the foundation of every well-governed cloud environment — it defines management groups, subscriptions, networking, policies, and RBAC in a consistent, repeatable way. Using Terraform alongside GitHub Actions gives you a fully automated, version-controlled pipeline for standing up production-ready Azure environments from scratch.
Prerequisites
Install Terraform 1.6 or later, the Azure CLI, and configure a service principal for Terraform to authenticate with Azure. Store the credentials as GitHub Actions secrets.
# Create Terraform service principal
$sp = New-AzADServicePrincipal -DisplayName "terraform-lz-deployer"
New-AzRoleAssignment -ObjectId $sp.Id `
-RoleDefinitionName "Owner" `
-Scope "/"
Write-Host "Client ID: $($sp.AppId)" Management Group and Subscription Structure
Define your management group hierarchy in Terraform to mirror your organisational structure and policy inheritance requirements.
resource "azurerm_management_group" "platform" {
display_name = "Platform"
}
resource "azurerm_management_group" "workloads" {
display_name = "Workloads"
parent_management_group_id = azurerm_management_group.platform.id
}
resource "azurerm_subscription" "prod" {
subscription_name = "Production"
billing_scope_id = var.billing_scope_id
management_group_id = azurerm_management_group.workloads.id
} Hub-and-Spoke Networking
Deploy a hub virtual network with VPN gateway and peer each spoke subscription back to the hub for centralised egress and inspection.
resource "azurerm_virtual_network" "hub" {
name = "vnet-hub"
resource_group_name = azurerm_resource_group.connectivity.name
location = var.location
address_space = ["10.0.0.0/16"]
}
resource "azurerm_virtual_network_peering" "hub_to_spoke" {
name = "hub-to-spoke"
resource_group_name = azurerm_resource_group.connectivity.name
virtual_network_name = azurerm_virtual_network.hub.name
remote_virtual_network_id = azurerm_virtual_network.spoke.id
allow_gateway_transit = true
} GitHub Actions CI/CD Pipeline
Run terraform plan on every pull request and terraform apply automatically on merge to main.
name: Landing Zone Deploy
on:
push:
branches: [main]
pull_request:
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- run: terraform init
- run: terraform plan -out=tfplan
- if: github.ref == 'refs/heads/main'
run: terraform apply tfplan Summary
Automating Azure Landing Zone deployment with Terraform and GitHub Actions ensures every new environment is consistent, policy-compliant, and production-ready from day one. The Git history becomes a complete audit trail of every infrastructure decision, and the CI/CD pipeline prevents untested changes from ever reaching production.