Focus area · 04

Sovereign migrations

Moving regulated workloads into the EU Data Boundary and migrating VMware estates to Azure Local — assessment, wave planning, and landing zone readiness.

The technical shape

The appliance is the boundary

For a VMware-to-Azure-Local migration, the Azure Migrate appliance and the Arc resource bridge are where the sovereignty argument either holds or doesn't: replication traffic needs to stay inside the target boundary, the appliance itself needs a landing zone to sit in before wave one starts, and "data residency" has to mean the migration path too — not just the steady state after cutover.

VMware to Azure Local migration flow inside the EU Data Boundary VMware vCenter and ESXi hosts connect to an Azure Migrate appliance, which connects to an Arc resource bridge, which replicates into an Azure Local target. A dashed boundary around the appliance, bridge and target marks the EU Data Boundary. VMware vCenter + ESXi Azure Migrate appliance Arc resource bridge replication path Azure Local target VM EU DATA BOUNDARY — REPLICATION NEVER LEAVES THIS PERIMETER needs its own landing zone

The appliance and the resource bridge sit inside the same boundary as the target — treat them as workloads that need a landing zone, not as transient tooling.

Code starting points

Standing up the migration project with a private path

The structural pattern: an Azure Migrate project, plus a private endpoint so appliance-to-service traffic uses a private path instead of the public internet. This is the network prerequisite people skip, then explain in an incident report. As always, check provider resource names and apiVersion against Microsoft Learn — Azure Migrate's Terraform coverage is newer and changes faster than core networking resources.

Terraform
resource "azurerm_resource_group" "migrate" {
  name     = "rg-migrate-sovereign"
  location = "westeurope"
}

resource "azurerm_migrate_project" "vmware_to_local" {
  name                = "migrate-vmware-to-azlocal"
  resource_group_name = azurerm_resource_group.migrate.name
  location            = azurerm_resource_group.migrate.location
}

# Network prerequisite: a private endpoint so appliance-to-service
# traffic never leaves the sovereign boundary
resource "azurerm_private_endpoint" "migrate_pe" {
  name                = "pe-migrate-vmware-to-azlocal"
  resource_group_name = azurerm_resource_group.migrate.name
  location            = azurerm_resource_group.migrate.location
  subnet_id           = azurerm_subnet.migrate.id

  private_service_connection {
    name                           = "migrate-connection"
    private_connection_resource_id = azurerm_migrate_project.vmware_to_local.id
    subresource_names              = ["migration"]
    is_manual_connection           = false
  }
}
Bicep
resource migrateProject 'Microsoft.Migrate/migrateProjects@2020-05-01' = {
  name: 'migrate-vmware-to-azlocal'
  location: 'westeurope'
  properties: {}
}

resource migratePrivateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = {
  name: 'pe-migrate-vmware-to-azlocal'
  location: 'westeurope'
  properties: {
    subnet: {
      id: migrateSubnetId
    }
    privateLinkServiceConnections: [
      {
        name: 'migrate-connection'
        properties: {
          privateLinkServiceId: migrateProject.id
          groupIds: [
            'migration'
          ]
        }
      }
    ]
  }
}