AZURE LANDING ZONE → STACKIT · ARCHITECTURE

Azure landing zones and the STACKIT target architecture

An Azure landing zone is a platform layer of management groups, subscriptions, a hub network, policy and central logging. STACKIT has folders, projects and a Network Area, but no policy engine and no managed firewall in the Terraform provider. This page shows what StackToIT drafts for each part of a hub-and-spoke zone and which design questions stay with your architects.

Management groups become folders

A demo landing zone written for this page and assessed by StackToIT on 4 November 2026: two management groups, a policy assignment, a hub and a spoke network with peering, a firewall, a route table, a Log Analytics workspace and a role assignment. Left: the input. Right: the resource blocks of the STACKIT Terraform the engine wrote; the review comments above each block are left out here.

Example inputmain.tf
resource "azurerm_management_group" "platform" {
  display_name = "Platform"
  name         = "mg-platform"
}

resource "azurerm_management_group" "landing_zones" {
  display_name               = "Landing Zones"
  name                       = "mg-landing-zones"
  parent_management_group_id = azurerm_management_group.platform.id
}
STACKIT Terraform by StackToITterraform/organisation.tf
resource "stackit_resourcemanager_folder" "platform" {
  name                = "Platform"
  parent_container_id = var.folder_parent_container_id
  owner_email         = var.folder_owner_email
}

resource "stackit_resourcemanager_folder" "landing_zones" {
  name                = "landing-zones"
  parent_container_id = stackit_resourcemanager_folder.platform.container_id
  owner_email         = var.folder_owner_email
}
  • The hierarchy survives

    The child management group becomes a child folder, through the reference to the parent folder. Check that against the STACKIT Resource Manager documentation, which states (as of November 2026) that STACKIT currently supports a single level of folder hierarchy: a folder inside a folder may not apply as drafted, so flatten the tree or place the second folder under the organization. The run notes that role assignments on a STACKIT folder apply to its projects; the STACKIT access-control page opened for this guide does not describe that inheritance, so test it before you rely on it.

  • The identifier does not

    The management group ID is not carried, because STACKIT assigns the folder ID itself. The display name is made a valid STACKIT name, so Landing Zones becomes landing-zones.

  • Values you supply

    The parent container and an owner e-mail address have no default: the folders go under the organization or an existing folder you name.

Peering becomes a Network Area

From the same run. Two VNets and their peerings are replaced by one Network Area for the organization. Networks of projects inside the area route to each other privately.

Example inputmain.tf
resource "azurerm_virtual_network_peering" "hub_to_spoke" {
  name                      = "hub-to-spoke-orders"
  resource_group_name       = azurerm_resource_group.hub.name
  virtual_network_name      = azurerm_virtual_network.hub.name
  remote_virtual_network_id = azurerm_virtual_network.spoke.id
}

resource "azurerm_virtual_network_peering" "spoke_to_hub" {
  name                      = "spoke-orders-to-hub"
  resource_group_name       = azurerm_resource_group.spoke.name
  virtual_network_name      = azurerm_virtual_network.spoke.name
  remote_virtual_network_id = azurerm_virtual_network.hub.id
}
STACKIT Terraform by StackToITterraform/network.tf
resource "stackit_network_area" "migrated" {
  organization_id = var.organization_id
  name            = "migrated-network-area"
}

resource "stackit_network_area_region" "migrated" {
  organization_id = var.organization_id
  network_area_id = stackit_network_area.migrated.network_area_id
  ipv4 = {
    network_ranges   = [for p in var.network_area_ranges : { prefix = p }]
    transfer_network = var.network_area_transfer_network
  }
}
  • Per-peering settings are gone

    The area has no per-peering settings, so the names, gateway transit, forwarded traffic and subnet selection of the peerings are not generated. The run asks you to check the routing of the area.

  • Projects join at creation

    The comment in the file states that the projects of the migrated networks must be created in the area with a networkArea label, and that this cannot be changed after the project exists. Decide the area before you create projects.

  • Ranges and transfer network

    The area takes the address spaces of the VNets as its ranges by default. The transfer network, a CIDR the networks do not use, has no default.

What the engine hands to an architect

The firewall, the route table and the policy assignment do not become resource blocks. Left: the three input blocks. Right: waves 1 and 3 of the run's sequencing file, migration/technical-sequencing.md, with the class and confidence of every unit; wave 2 is left out here. The input blocks are not adjacent in main.tf, so each has its own pane, verbatim.

Input: azurerm_subscription_policy_assignment.allowed_locationsmain.tf
resource "azurerm_subscription_policy_assignment" "allowed_locations" {
  name                 = "allowed-locations"
  subscription_id      = "/subscriptions/00000000-0000-0000-0000-000000000000"
  policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c"

  parameters = jsonencode({
    listOfAllowedLocations = { value = ["germanywestcentral", "northeurope"] }
  })
}
Input: azurerm_firewall.hub, azurerm_route_table.spokemain.tf
resource "azurerm_firewall" "hub" {
  name                = "fw-hub"
  location            = azurerm_resource_group.hub.location
  resource_group_name = azurerm_resource_group.hub.name
  sku_name            = "AZFW_VNet"
  sku_tier            = "Standard"

  ip_configuration {
    name                 = "primary"
    subnet_id            = azurerm_subnet.firewall.id
    public_ip_address_id = azurerm_public_ip.firewall.id
  }
}

resource "azurerm_route_table" "spoke" {
  name                = "rt-spoke-orders"
  location            = azurerm_resource_group.spoke.location
  resource_group_name = azurerm_resource_group.spoke.name

  route {
    name                   = "default-via-firewall"
    address_prefix         = "0.0.0.0/0"
    next_hop_type          = "VirtualAppliance"
    next_hop_in_ip_address = "10.0.0.4"
  }
}
StackToIT migration planmigration/technical-sequencing.md
## Wave 1 — 7 unit(s)

| Unit | Class | Target |
|---|---|---|
| `azurerm_log_analytics_workspace.platform` | RECONFIGURE / MEDIUM | STACKIT Logs / Observability |
| `azurerm_management_group.platform` | RECONFIGURE / MEDIUM | STACKIT folder |
| `azurerm_public_ip.firewall` | RECONFIGURE / MEDIUM | implicit (belongs to the gateway, firewall or load balancer) |
| `azurerm_route_table.spoke` | MANUAL_REVIEW / LOW | — |
| `azurerm_subscription_policy_assignment.allowed_locations` | REDESIGN / MEDIUM | none managed — policy as code in the delivery pipeline (e.g. OPA/Conftest, Checkov) |
| `azurerm_virtual_network.hub` | RECONFIGURE / MEDIUM | STACKIT project networking / Network Area (SNA) |
| `azurerm_virtual_network.spoke` | RECONFIGURE / MEDIUM | STACKIT project networking / Network Area (SNA) |

## Wave 3 — 1 unit(s)

| Unit | Class | Target |
|---|---|---|
| `azurerm_firewall.hub` | MANUAL_REVIEW / LOW | — |
  • Azure Firewall: MANUAL_REVIEW

    The run says Azure Firewall has no general-availability STACKIT equivalent. STACKIT Unified Firewall is an opt-in feature that may still change and is not yet in the Terraform provider, so the design chooses between it, security groups or a firewall appliance on STACKIT servers.

  • Route table: MANUAL_REVIEW

    The routes the scan lists are a lower bound, because BGP route propagation is on by default and may add routes the configuration does not write. A table drafted from the listed routes would be narrower than the source, so none is drafted and the Network Architect decides.

  • Policy assignment: REDESIGN

    STACKIT has no policy engine equivalent. The guardrails move into the pipeline that applies the Terraform (policy as code, for example OPA or Checkov) and into the role design of the organization.

How the landing zone maps

Azure resourceSTACKIT targetMigration class
Management groupsSTACKIT foldersReconfigure
Policy assignmentNo managed counterpart: policy as code in the delivery pipelineRedesign
Hub and spoke VNetsNetwork Area and STACKIT networksReconfigure
VNet peeringsNetwork Area, region and routesReconfigure
Workload subnetSTACKIT network with the same IPv4 prefixReconfigure
Firewall subnet and public IPNo resource: they belong to the Azure firewallReconfigure
Azure FirewallDecided by an architectArchitect decision
Route table with a virtual-appliance routeRouting table decided once the route set is knownArchitect decision
Log Analytics workspaceSTACKIT Logs instance (and Observability for metrics)Reconfigure

Classes as the run decided them: 10 RECONFIGURE, 2 MANUAL_REVIEW and 1 REDESIGN across 13 units. 6 of them were drafted, 4 need no resource and 3 are held for a person.

Three ways to build the target

The run proposes one target per unit, not an organization. These are the layouts architects usually weigh, and what each means for the units above. The layouts are practice; the assessment of each unit is from the run.

LayoutWhat it meansWatch for
Folders and one project per workload environment, joined by a Network AreaClosest to a landing zone: platform and workload folders, private routing between projects, roles on folders. The run drafts this shape.The area and the project label are fixed at creation. The area is enabled per region, and the STACKIT documentation says traffic between regions currently goes over the public internet.
Folders and projects without a Network AreaEach project keeps its own network and is reached through service endpoints and access lists.Hub-and-spoke routing and central egress have no equivalent, so workloads that relied on the hub are redesigned.
Network Area with a firewall appliance on serversForced routing through a central appliance, as the hub firewall did.You run and patch the appliance, and the run does not draft it. Decide the routes first.

Decide in this order

  1. 1. Organization and folders

    The network area and routing tables are organization resources, and the folders sit under the container you name. Fix this first; the other steps need its IDs.

  2. 2. The network area and its ranges

    Choose the ranges and the transfer network, then create the projects inside the area. Do not create them first.

  3. 3. Projects and roles

    The resource group scope of each resource is an open setting. STACKIT has no resource groups, so you map the boundaries of the old groups to projects and to roles on folders and projects.

  4. 4. Routes and egress

    Take the routing decision the run raised, and decide how outbound traffic leaves the networks. The run could not prove how the workload subnet reached the internet in Azure.

  5. 5. Logging

    The draft creates a Logs instance with 90 days of retention. Before a source writes to it, create a write access token and set the access list; the draft does neither.

  6. 6. Guardrails as code

    Port the policy assignment into the pipeline that applies the Terraform before the first workload is applied.

What the Azure landing zone has that STACKIT does not

  • Subscriptions as a vending unit

    The run treats each subscription and resource group as a layout question. STACKIT projects play the role, and creating them is a process you design.

  • Central policy

    No managed engine evaluates resources against rules. Your delivery pipeline does.

  • Managed central firewall

    Not available as a drafted resource; the design decides.

  • Workspace-based monitoring

    KQL queries, workbooks and alerts are rewritten for the tools of the STACKIT Logs and Observability services.

Questions platform teams ask

Does a management group map to a folder one to one?

The run writes a folder for each management group and keeps the parent relation. STACKIT documents a single level of folder hierarchy as of November 2026, so a deeper management group tree has to be flattened. The management group ID is not carried and the folder is named from the display name.

What replaces VNet peering?

A STACKIT Network Area for the organization. Networks of projects in the area route to each other privately, and the platform adjusts the routing tables of the project routers. The area is enabled per region.

Where do Azure Policy rules go?

Into policy as code in the pipeline that applies the Terraform, and into role design. The run classifies a policy assignment as REDESIGN because there is no equivalent engine.

Is a firewall part of the draft?

No. Azure Firewall is classified MANUAL_REVIEW with LOW confidence, and the draft contains no firewall resource. The architects decide between an opt-in STACKIT firewall feature, security groups or an appliance.

Sources

Your next move: STACKIT.

Tell us about your estate. We show you what StackToIT delivers for it: target architecture, Terraform artifacts and a structured migration plan.