AWS VPC → STACKIT NETWORK
AWS VPC and network migration to STACKIT
STACKIT has no VPC object: subnets become STACKIT networks in a project, and networks that talk privately join a Network Area. StackToIT carries the prefixes and DNS servers and turns what STACKIT does differently, such as NAT egress addresses, into clear decisions.
Subnets keep their prefixes
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.
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "private_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "eu-central-1a"
}
resource "aws_subnet" "private_b" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "eu-central-1b"
}resource "stackit_network" "private_a" {
project_id = var.project_id
name = "private-a"
ipv4_prefix = "10.0.1.0/24"
ipv4_nameservers = var.default_ipv4_nameservers
}
resource "stackit_network" "private_b" {
project_id = var.project_id
name = "private-b"
ipv4_prefix = "10.0.2.0/24"
ipv4_nameservers = var.default_ipv4_nameservers
}The community VPC module, converted
From the published AWS Retail Store run. Its subnets are computed from the availability zones, so their number and prefixes become variables you set once. The review comments above each block in the file are left out here.
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.21.0"
name = var.environment_name
cidr = var.vpc_cidr
azs = local.azs
public_subnets = local.public_subnets
private_subnets = local.private_subnets
enable_nat_gateway = true
create_igw = true
enable_dns_hostnames = true
single_nat_gateway = true
# Manage so we can name
manage_default_network_acl = true
default_network_acl_tags = { Name = "${var.environment_name}-default" }
manage_default_route_table = true
default_route_table_tags = { Name = "${var.environment_name}-default" }
manage_default_security_group = true
default_security_group_tags = { Name = "${var.environment_name}-default" }
public_subnet_tags = merge(var.tags, var.public_subnet_tags)
private_subnet_tags = merge(var.tags, var.private_subnet_tags)
tags = var.tags
}resource "stackit_network" "vpc_vpc_private" {
count = var.private_count
project_id = var.project_id
name = "vpc-vpc-private-${count.index}"
ipv4_prefix = var.private_ipv4_prefixes[count.index]
ipv4_nameservers = var.default_ipv4_nameservers
}
resource "stackit_network" "vpc_vpc_public" {
count = var.public_count
project_id = var.project_id
name = "vpc-vpc-public-${count.index}"
ipv4_prefix = var.public_ipv4_prefixes[count.index]
ipv4_nameservers = var.default_ipv4_nameservers
}How the network maps
| AWS resource | STACKIT target | Migration class |
|---|---|---|
| VPC | STACKIT project networking or Network Area | Reconfigure |
| Subnets | STACKIT networks with the same IPv4 prefixes | Reconfigure |
| Internet gateway | Built into a routed STACKIT network | Reconfigure |
| NAT gateway | STACKIT default routing with outbound NAT | Reconfigure |
| Route tables | STACKIT default routing or Network Area routing tables | Reconfigure |
| Security groups | STACKIT security groups and rules | Reconfigure |
| Network ACLs | STACKIT security groups (stateful) | Redesign |
Classes as the AWS Retail Store run decided them.
Decisions the run raises for your network team
Egress address
A NAT gateway gives a fixed egress address. On STACKIT the address is the network’s own, so StackToIT asks whether servers on allow lists get STACKIT public IPs.
Private DNS
Names that only the AWS VPC resolver answers need a DNS server of your own. StackToIT points out where the source relies on it.
Project or Network Area
Whether the target project sits in a Network Area changes routing and cluster placement, so the run records it as a decision before the pilot.
What the Retail Store network became
The community VPC module of the published run, resource group by resource group.
| AWS resources | In the run | On STACKIT |
|---|---|---|
| VPC | 1 unit | Network Area and networks |
| Subnets | 7 in the module; private and public are switched on, five more are switched off | One STACKIT network each for the two switched on; the others would be networks if switched on |
| NAT gateway and its address | 1 gateway, set to a single NAT | Outbound routing of the STACKIT network; the address belongs to the network |
| Internet gateway | 1 | The default gateway of the STACKIT network |
| Route tables | 6; private and public are switched on | Default routing of the network |
| Network ACLs | 7, all switched off in the source | Would become security groups, since STACKIT has no stateless ACLs |
| Security groups | 15: 7 drafted, 5 for managed data services, 3 switched off | STACKIT security groups and rules for the 7; the 5 reach the data services as access-list addresses |
Counts from the published AWS Retail Store run; switched off means the source configuration does not create the resource.
More network decisions the run opens
All of them are due before the pilot and carry an owner.
Workload placement (Network Architect)
A Kubernetes Engine cluster is deployed into one network, and a database, cache or broker takes an access list and no network id. The options are one network for cluster and services, the source networks with placement by tier, a redesign, or consumers outside the network.
Pod segmentation (Security Architect)
The five service security groups cannot be proven to mean one thing on Kubernetes. The options are NetworkPolicy written from the group rules, a security group on the nodes, or no segmentation.
Load balancer path (Network Architect)
A target pool reaches targets by private IP, and the cluster exports no node address to Terraform. A workload is reachable through a node port or through an Ingress controller.
Which network instance (Platform Architect)
The load balancer refers to a repeated public network. Nothing in the source says which instance is meant, so no instance is assumed.
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
Does STACKIT have a VPC?
Not as a GA container object. A project with its networks is the boundary, and a Network Area connects networks privately. The newer stackit_vpc resources are an opt-in provider feature that may still change, so StackToIT does not use them.
Are our CIDR ranges kept?
Yes. A subnet becomes a STACKIT network with the same IPv4 prefix.
What happens to security groups?
STACKIT security groups are stateful like AWS’s, including rules that reference another group, so StackToIT re-creates the rules one by one.
Do Network ACLs carry over?
STACKIT has no stateless network ACLs. The module in the published run defines seven, all switched off in the source, so the run drafted none. Switched on, they would be rebuilt as stateful security groups, which is a redesign.
Why do the databases get no security group?
STACKIT’s managed data services have no security group and take their clients from an access list of their own. In the run, five source groups were not drafted for this reason, and what they admitted reaches the access lists as addresses.
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.