AZURE → STACKIT · COMPLETE GUIDE
The complete Azure to STACKIT migration guide
Start from the Terraform you already have for Azure. StackToIT reads it, classifies every resource, drafts the STACKIT Terraform it can and lists, per owner role, what only a person can decide. You then lay out the landing zone, apply in waves, move the data and cut over. This guide follows that order and shows a real run on a mixed estate of 11 resources.
The migration in eight steps
Each step names the file of the run that holds its answer. The files are in the output folder that the assess command writes.
1. Collect the Terraform
Gather the root modules for AzureRM or AzAPI, with their variable files. A variable without a value leaves a unit without a draft, so hand the engine the same files your pipeline uses. StackToIT reads the code only and does not connect to an Azure account.
2. Run the assessment
Run stacktoit assess on the folder. The console prints the source figures, how many units were drafted and how many open requests there are. Open index.html first.
3. Answer the first requests
review/inputs.yaml lists the typed questions. One blocks the draft: the target region. Others, such as the allowed CIDRs of each managed service, are variables of the draft.
4. Review decisions by owner role
review/decisions.yaml holds one record per owner role and unit. A review records that someone looked; it frees no step until the draft is regenerated with the answers.
5. Lay out the target
Create the folders and the project, and a Network Area if networks must reach each other. migration/landing-zone-requirements.md lists what the organization has to provide before the first apply.
6. Apply in waves
migration/technical-sequencing.md orders units by dependency. In the run below, the managed services and the network come first, the subnet next, the server after it and the data disk last, because it is attached to the server.
7. Move the data
migration/data-movement.md lists every stateful unit with the mechanism UNKNOWN until a person chooses one. StackToIT never moves data.
8. Cut over and close the settings
Switch the applications, then close or accept each open critical setting in execution/manual/actions.md. Keep the Azure side until the checks are done.
Step 2: run the assessment
A mixed demo estate written for this guide: a virtual network with one subnet, a Linux VM with a data disk, a Redis cache, a Service Bus namespace with a queue and a Cosmos DB account with the MongoDB API. The run is dated 4 November 2026. The summary lines are copied from the console of that run.
stacktoit assess . ./out --offline --no-validateSource 11 resources · 7 units · visibility: Complete
Migration 6 drafted · 1 need no resource (of 7 units the draft considered)
Target STACKIT Terraform generated
Attention 7 units to review · 5 open requests (1 block the draft, marked in inputs-template.yaml)11 resources, 7 units
The queue folds into its namespace, the data disk attachment into the disk and the NIC into the VM; the resource group is not a unit. Six units were drafted and one needs no resource, the virtual network.
What the run created
OpenTofu steps for 10 resource blocks, and 16 manual steps in 11 work packages for the 25 critical settings the draft does not carry.
Compute: a VM and its disk
Left: the Linux VM and the managed data disk. Right: the server and volume blocks the engine wrote; the review comments above each block are left out here.
resource "azurerm_linux_virtual_machine" "batch" {
name = "vm-batch-01"
location = azurerm_resource_group.core.location
resource_group_name = azurerm_resource_group.core.name
size = "Standard_D4s_v5"
admin_username = "azureuser"
network_interface_ids = [azurerm_network_interface.batch.id]
admin_ssh_key {
username = "azureuser"
public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyOnlyForTheDemo demo"
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Premium_LRS"
disk_size_gb = 64
}
source_image_reference {
publisher = "Canonical"
offer = "ubuntu-24_04-lts"
sku = "server"
version = "latest"
}
}
resource "azurerm_managed_disk" "batch_data" {
name = "disk-batch-data"
location = azurerm_resource_group.core.location
resource_group_name = azurerm_resource_group.core.name
storage_account_type = "Premium_LRS"
create_option = "Empty"
disk_size_gb = 256
}resource "stackit_server" "batch" {
project_id = var.project_id
name = "vm-batch-01"
machine_type = var.batch_machine_type
availability_zone = var.availability_zone
boot_volume = {
source_type = "image"
source_id = var.batch_image_id
size = 64
delete_on_termination = true
}
keypair_name = stackit_key_pair.batch.name
network_interfaces = [stackit_network_interface.batch_1.network_interface_id]
}
resource "stackit_volume" "batch_data" {
project_id = var.project_id
name = "disk-batch-data"
availability_zone = var.availability_zone
size = 256
performance_class = var.batch_data_performance_class
}Size, image and login are variables
The machine type and the image ID have no default. The Azure VM size does not map to a name; you choose a STACKIT machine type. The admin user azureuser is not carried: the login user is the one of the image.
Disk performance is a choice
The boot volume keeps its size and loses caching and the Premium_LRS type; the data volume takes the 256 size as given and a performance class variable. Attach by volume ID in the guest, not by LUN, because the LUN is not carried.
Order matters
The disk is the last unit, because it attaches to a server that must exist first.
Managed services: cache and messaging
From the same run. First pane: the Redis cache and the Service Bus namespace. Then the Valkey and RabbitMQ instances, one pane per draft file. The queue and the namespace settings are not generated.
resource "azurerm_redis_cache" "sessions" {
name = "redis-sessions-gwc"
location = azurerm_resource_group.core.location
resource_group_name = azurerm_resource_group.core.name
capacity = 1
family = "C"
sku_name = "Standard"
minimum_tls_version = "1.2"
}
resource "azurerm_servicebus_namespace" "events" {
name = "sb-events-gwc"
location = azurerm_resource_group.core.location
resource_group_name = azurerm_resource_group.core.name
sku = "Standard"
}resource "stackit_valkey_instance" "sessions" {
project_id = var.project_id
name = "redis-sessions-gwc"
plan_name = var.sessions_plan_name
version = var.sessions_version
parameters = {
sgw_acl = join(",", var.sessions_allowed_cidrs)
}
}resource "stackit_rabbitmq_instance" "messaging" {
project_id = var.project_id
name = "messaging"
plan_name = var.rabbitmq_plan_name
version = var.rabbitmq_version
parameters = {
sgw_acl = join(",", var.rabbitmq_allowed_cidrs)
}
}Access lists have no safe default
The draft sets the access list from variables without a default. The comment says that without a list STACKIT applies its default ACL, which covers the addresses of every STACKIT customer. List the client CIDRs before you plan.
A new client protocol
Service Bus speaks AMQP 1.0. The run names an AMQP 0-9-1 client for RabbitMQ, so producers and consumers change their library, and the queue is recreated by hand.
The cache size is a plan
Family and capacity are not carried. You choose the Valkey plan, and clients get new credentials; cached data is usually rebuilt, not migrated.
How the estate maps
| Azure resource | STACKIT target | Migration class |
|---|---|---|
| Linux virtual machine (with NIC) | Compute Engine server and network interface | Reconfigure |
| Managed disk (with attachment) | Block Storage volume attached to the server | Reconfigure |
| Virtual network | STACKIT project networking or Network Area | Reconfigure |
| Subnet | STACKIT network with the same IPv4 prefix | Reconfigure |
| Azure Cache for Redis | Key Value Store (Valkey) instance and credential | Reconfigure |
| Service Bus namespace (with queue) | RabbitMQ instance | Replatform |
| Cosmos DB account, MongoDB API | MongoDB Flex instance | Replatform |
Classes as the run decided them: 5 RECONFIGURE and 2 REPLATFORM, all with MEDIUM confidence. Other services follow the same pattern; the Azure SQL, AKS and network guides show their own runs.
How the data moves, by service
MongoDB API
The wire protocol is the same, so clients move with a new connection string, TLS CA and credentials. Data moves with mongodump and mongorestore. Global distribution, tunable consistency and request-unit scaling do not carry over.
Cache
Cached data is usually rebuilt, not migrated. Only state you cannot rebuild, such as sessions you must keep, needs a plan.
Queues
Drain or replay in-flight messages and recreate queues, exchanges and bindings in RabbitMQ. The run lists the namespace as a unit but not as stateful data.
Disks
A managed disk becomes a volume of the same size. The data moves with the server image or with a file or block copy; the engine records the mechanism as undecided.
Decisions your architects own
Identity
Who signs in to the new services. The run opens settings for the administrator login of the VM and the resource group scope of every unit; STACKIT has no resource groups, so map their boundaries to projects and roles.
Network exposure
Whether each managed service is public or scoped to a Network Area, and which CIDRs may reach it.
Sizing
Machine type, Valkey plan, MongoDB flavor and storage classes. None of these has a default in the draft.
Data movement
Mechanism, window and tolerated downtime per stateful unit. The source states none of them.
Residency
The location of each resource is an open setting; confirm the region and that the services exist in it.
Questions migration leads ask
Does StackToIT connect to my Azure subscription?
No. It reads Terraform and OpenTofu root modules written with the azurerm or azapi provider, offline if you ask for it. It does not read a live account, so resources created outside Terraform are not seen.
Can I apply the generated Terraform right away?
No. The package is a proposal for your architects to review. In this run none of the OpenTofu steps can run as written, because values such as project_id and the access lists are missing and settings are open.
Which Azure services have a managed STACKIT target?
Per the curated mapping: AKS to SKE, PostgreSQL and SQL Server to their Flex services, storage accounts to Object Storage, Key Vault to Secrets Manager and KMS, Redis to Valkey, Service Bus to RabbitMQ and Cosmos DB to MongoDB Flex or PostgreSQL Flex. App Service and Functions go to Cloud Foundry or SKE. Azure Firewall is decided case by case.
Where do I start inside the output folder?
Open index.html, then read engineering/architect-report.md for the findings per unit, review/inputs.yaml and review/decisions.yaml for the questions, and execution/README.md for the order of the steps.
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.