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.