AZURE VNET → STACKIT NETWORKS

Azure VNet, subnets and NSGs to STACKIT

An Azure virtual network moves to STACKIT as one network per subnet with the same IPv4 prefixes, and network security groups become STACKIT security groups attached to the servers. StackToIT carries every rule it can read as a rule and names each Azure default that STACKIT handles differently.

A VNet with two subnets, converted

A small estate written for this page and assessed by StackToIT on 4 November 2026. Left: the input. Right: the resource blocks of the STACKIT Terraform the engine wrote; the review comments that sit above each block in the file are left out here.

Example inputmain.tf
resource "azurerm_virtual_network" "shop" {
  name                = "vnet-shop"
  location            = azurerm_resource_group.net.location
  resource_group_name = azurerm_resource_group.net.name
  address_space       = ["10.30.0.0/16"]
}

resource "azurerm_subnet" "web" {
  name                 = "snet-web"
  resource_group_name  = azurerm_resource_group.net.name
  virtual_network_name = azurerm_virtual_network.shop.name
  address_prefixes     = ["10.30.1.0/24"]
}

resource "azurerm_subnet" "app" {
  name                 = "snet-app"
  resource_group_name  = azurerm_resource_group.net.name
  virtual_network_name = azurerm_virtual_network.shop.name
  address_prefixes     = ["10.30.2.0/24"]
}
STACKIT Terraform by StackToITterraform/network.tf
resource "stackit_network" "app" {
  project_id       = var.project_id
  name             = "snet-app"
  ipv4_prefix      = "10.30.2.0/24"
  ipv4_nameservers = var.default_ipv4_nameservers
}

resource "stackit_network" "web" {
  project_id       = var.project_id
  name             = "snet-web"
  ipv4_prefix      = "10.30.1.0/24"
  ipv4_nameservers = var.default_ipv4_nameservers
}
  • One network per subnet

    STACKIT has no VNet container. snet-web and snet-app become two STACKIT networks in the project; networks that must reach each other privately join a Network Area.

  • Prefixes kept

    10.30.1.0/24 and 10.30.2.0/24 stay the prefixes of the new networks, so the address plan stays as it is.

  • Nameservers set

    The networks read their nameservers from one variable. Its default is the STACKIT DNS Resolver in eu01, and the code notes that private names need a DNS server of their own.

A network security group, converted

From the same run. Left: the input. Right: the resource blocks StackToIT wrote; the review comments above each block, and the inactive HTTPS rule the file carries as a comment block, are left out here.

Example inputmain.tf
resource "azurerm_network_security_group" "web" {
  name                = "nsg-web"
  location            = azurerm_resource_group.net.location
  resource_group_name = azurerm_resource_group.net.name

  security_rule {
    name                       = "allow-https"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "443"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }

  security_rule {
    name                       = "allow-ssh-from-admin"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "203.0.113.0/24"
    destination_address_prefix = "*"
  }
}

resource "azurerm_subnet_network_security_group_association" "web" {
  subnet_id                 = azurerm_subnet.web.id
  network_security_group_id = azurerm_network_security_group.web.id
}
STACKIT Terraform by StackToITterraform/security.tf
resource "stackit_security_group" "web" {
  project_id = var.project_id
  name       = "nsg-web"
}

resource "stackit_security_group_rule" "web_allow_ssh_from_admin" {
  project_id        = var.project_id
  security_group_id = stackit_security_group.web.security_group_id
  direction         = "ingress"
  ether_type        = "IPv4"
  ip_range          = "203.0.113.0/24"
  port_range = {
    max = 22
    min = 22
  }
  protocol = {
    name = "tcp"
  }
}
  • Rules with addresses carry over

    The SSH rule from 203.0.113.0/24 becomes an active STACKIT security group rule for TCP port 22. STACKIT rules are stateful, so return traffic needs no rule of its own.

  • Service tags become a decision

    The HTTPS rule allows the service tag Internet. STACKIT has no service tag selector, so the code writes the rule as an inactive block in the file and asks your security architect for the address ranges.

  • Priorities fall away safely

    STACKIT rules have no priority. No deny rule of the estate outranks an allow rule, so the code drops no allow rule and writes them as unordered STACKIT rules.

  • Attached per server

    The NSG sits on snet-web. STACKIT security groups attach to the network interface of each server, so the group goes on every migrated server of that subnet.

Azure defaults the code names

Every NSG carries rules nobody wrote. STACKIT starts from different defaults, and the run lists each difference in the file.

  • Inbound from the VNet and the load balancer

    A new STACKIT security group allows no incoming traffic until a rule says so. The code asks for explicit rules where the traffic of AllowVnetInBound and AllowAzureLoadBalancerInBound must keep flowing.

  • Traffic inside the group

    Members of a user-created STACKIT group reach each other only with an explicit ingress rule. The code says where one is needed.

  • Default egress

    STACKIT creates an allow-all IPv4 egress rule on every new group. The source egress is narrower, so you decide whether to delete the default rule after apply or accept the wider egress.

  • Changes take effect within a minute

    In nine measurements a rule change reached the data plane 27 to 50 seconds after the API answered. The code says to verify after a minute, not straight away.

How the network estate maps

Azure resourceSTACKIT targetMigration class
Virtual networkSTACKIT project networking or Network AreaReconfigure
SubnetsSTACKIT networks with the same IPv4 prefixesReconfigure
Network security group and its subnet associationSTACKIT security group with its rulesReconfigure

Classes as the run decided them. The run lists eight decisions for this estate, from the service tag to the default egress, each written into the decisions file.

Proven on a real AWS estate

The AWS Retail Store Sample App, a public Terraform project from AWS, assessed by StackToIT and published in full, exactly as the run wrote it.

View Case Study
282
Terraform resource declarations analyzed
44
migration units identified
38
target units generated, from 52 considered
331
plan steps written

Questions network teams ask

Do Azure NSG rules map to STACKIT security group rules?

Allow rules with protocol, port and address range become STACKIT security group rules, which are stateful. Priorities, deny rules and service tags have no counterpart, and StackToIT names each one for your architects.

What happens to the subnet association of an NSG?

STACKIT security groups attach to network interfaces, not to networks. The group is attached to every migrated server of the subnet the NSG was associated with.

Do our IP ranges change?

No. Each subnet becomes a STACKIT network with the same IPv4 prefix, so your address plan stays as it is.

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.