Skip to content

Subnets

Each Microtec ERP environment VNet is divided into seven subnets with distinct purposes, NSG profiles, and service delegation requirements.


Subnet Overview Table

Subnet NameCIDR SuffixSizePurposeServices
gatewaySubnet.0.0/2732 IPsVPN/ExpressRoute gatewayAzure VPN Gateway (reserved)
publicApps.1.0/24256 IPsInternet-facing Container AppsGateway.API, Keycloak
privateApps.2.0/23512 IPsVNet-internal Container AppsAll other microservices
appService.4.0/24256 IPsApp Service VNet integrationApp Service instances
functionApps.5.0/24256 IPsFunction App VNet integrationAzure Functions
privateEndpoints.6.0/24256 IPsPaaS private endpointsSQL, Redis, Service Bus, Storage, KV, ACR
sqlMi.7.0/24256 IPsReserved for SQL Managed InstanceSQL MI (if adopted)

CIDR suffix applies to each environment's /16 base:

  • dev: 10.0.
  • stage: 10.1.
  • preprod: 10.6.
  • uat: 10.5.
  • production: 10.2.

privateApps is /23, not /24

The privateApps subnet uses a /23 prefix (512 IPs), spanning .2.0 through .3.255. This is intentional — Azure Container Apps environments require a large address space for infrastructure-managed IPs. Do not reduce this to /24.


Subnet 1: publicApps (.1.0/24)

Full CIDR examples: 10.0.1.0/24 (dev), 10.2.1.0/24 (prod)

This subnet hosts the Public Azure Container Apps Environment, which is the only internet-reachable compute in the platform.

Services Deployed

ServiceInternal PortPublic Port
Gateway.API80443 (via Front Door)
Keycloak8080443 (via Front Door)

Subnet Delegation

Azure Container Apps requires subnet delegation:

bicep
// In vnet.bicep
resource publicAppsSubnet 'Microsoft.Network/virtualNetworks/subnets@2023-05-01' = {
  name: 'publicApps'
  properties: {
    addressPrefix: '${vnetCidrBase}.1.0/24'
    delegations: [
      {
        name: 'Microsoft.App/environments'
        properties: {
          serviceName: 'Microsoft.App/environments'
        }
      }
    ]
    networkSecurityGroup: {
      id: publicAppsNsg.id
    }
  }
}

NSG Rules

Inbound:
  Priority 100: Allow HTTPS (443) from AzureFrontDoor.Backend
  Priority 110: Allow HTTP (80) from AzureFrontDoor.Backend
  Priority 120: Allow health probe (65503-65534) from AzureLoadBalancer
  Priority 900: Deny all inbound from Internet

Outbound:
  Priority 100: Allow HTTPS (443) to privateApps subnet (10.x.2.0/23)
  Priority 110: Allow HTTPS (443) to privateEndpoints subnet (10.x.6.0/24)
  Priority 120: Allow DNS (53) to 168.63.129.16
  Priority 900: Deny all

Important: Inbound HTTPS should only be allowed from AzureFrontDoor.Backend service tag, not from Internet directly. This ensures all traffic passes through WAF.


Subnet 2: privateApps (.2.0/23)

Full CIDR examples: 10.0.2.0/23 (dev, covers 10.0.2.0–10.0.3.255), 10.2.2.0/23 (prod, covers 10.2.2.0–10.2.3.255)

This subnet hosts the Private Azure Container Apps Environment. Services here are never directly reachable from the internet — all traffic must originate from the publicApps subnet (Gateway) or from other privateApps services.

/23 Requirement

Azure Container Apps environments consume a significant number of IPs for internal infrastructure (load balancers, nodes, DNS). The /23 block provides 512 addresses, which Azure requires for a fully scaled environment.

Services Deployed

All microservices except Gateway and Keycloak:

AppsPortal.Apis         BusinessOwners.Apis
BusinessOwners.AdminPortal  Notification.Apis
Attachment.Apis         Workflows.Apis
Integration.Apis        Hr.Personnel.Apis
Inventory.Apis          Template.Blazor
Platforms.Worker

mTLS Enforcement

The Private CAE enforces mutual TLS for all service-to-service communication. Container Apps injects the mTLS certificates automatically; no application-level code changes are required.

bicep
resource privateCae 'Microsoft.App/managedEnvironments@2023-11-02-preview' = {
  properties: {
    peerAuthentication: {
      mtls: {
        enabled: true
      }
    }
    vnetConfiguration: {
      infrastructureSubnetId: privateAppsSubnet.id
      internal: true      // No public IP
    }
  }
}

NSG Rules

Inbound:
  Priority 100: Allow all TCP from publicApps subnet (10.x.1.0/24) — Gateway calls
  Priority 110: Allow all TCP from privateApps subnet (10.x.2.0/23) — service-to-service
  Priority 120: Allow health probe from AzureLoadBalancer
  Priority 900: Deny all (blocks internet)

Outbound:
  Priority 100: Allow HTTPS (443) to privateEndpoints subnet (10.x.6.0/24)
  Priority 110: Allow AMQP (5671,5672) to privateEndpoints subnet (Service Bus)
  Priority 120: Allow Redis (6380) to privateEndpoints subnet
  Priority 130: Allow DNS (53) to 168.63.129.16
  Priority 900: Deny all

Subnet 3: privateEndpoints (.6.0/24)

Full CIDR examples: 10.0.6.0/24 (dev), 10.2.6.0/24 (prod)

This subnet contains the private endpoint NICs for all PaaS services. A private endpoint gives a PaaS service a private IP within the VNet, making it reachable without traversing the public internet.

Subnet Offset is .6, not .2 or .3

The private endpoints subnet starts at .6.0/24. Earlier documents incorrectly showed .2.0/24 or .3.0/24. Private endpoint IPs will be in the 10.x.6.x range.

Private Endpoints Provisioned

ServicePrivate DNS ZoneApprox IP (dev)
Azure SQL Serverprivatelink.database.windows.net10.0.6.4
Redis Cacheprivatelink.redis.cache.windows.net10.0.6.5
Service Busprivatelink.servicebus.windows.net10.0.6.6
Key Vaultprivatelink.vaultcore.azure.net10.0.6.7
ACRprivatelink.azurecr.io10.0.6.8
Blob Storageprivatelink.blob.core.windows.net10.0.6.9
Cosmos DB (prod)privatelink.mongo.cosmos.azure.com10.2.6.10

No Subnet Delegation

Unlike compute subnets, the privateEndpoints subnet requires no delegation. However, it must have privateEndpointNetworkPolicies disabled:

bicep
resource privateEndpointsSubnet 'Microsoft.Network/virtualNetworks/subnets@2023-05-01' = {
  name: 'privateEndpoints'
  properties: {
    addressPrefix: '${vnetCidrBase}.6.0/24'
    privateEndpointNetworkPolicies: 'Disabled'    // Required for private endpoints
    networkSecurityGroup: {
      id: privateEndpointsNsg.id
    }
  }
}

NSG Rules

Inbound:
  Priority 100: Allow all from privateApps subnet (10.x.2.0/23)
  Priority 110: Allow all from publicApps subnet (10.x.1.0/24)
  Priority 900: Deny all

Outbound:
  Priority 900: Deny all    // PaaS services don't need outbound

Subnet 4: sqlMi (.7.0/24)

Full CIDR examples: 10.0.7.0/24 (dev), 10.2.7.0/24 (prod)

This subnet is reserved for Azure SQL Managed Instance if the platform migrates from the shared SQL VM to a managed PaaS offering. Currently unused.

SQL MI has strict subnet requirements:

  • Minimum /27 (32 IPs), recommended /24
  • Dedicated delegation: Microsoft.Sql/managedInstances
  • No other services in the subnet
bicep
// Reserved — not currently provisioned
resource sqlMiSubnet 'Microsoft.Network/virtualNetworks/subnets@2023-05-01' = if (deployManagedInstance) {
  name: 'sqlMi'
  properties: {
    addressPrefix: '${vnetCidrBase}.7.0/24'
    delegations: [
      {
        name: 'Microsoft.Sql/managedInstances'
        properties: {
          serviceName: 'Microsoft.Sql/managedInstances'
        }
      }
    ]
  }
}

Subnet IP Allocation Reference

For the production environment (10.2.0.0/16):

10.2.0.0/27   — gatewaySubnet (VPN/ER gateway)

10.2.1.0/24   — publicApps
  10.2.1.4    — Gateway.API (first assignable)
  10.2.1.5    — Keycloak
  10.2.1.6-254 — Reserved for scale-out replicas

10.2.2.0/23   — privateApps (covers 10.2.2.0 through 10.2.3.255)
  10.2.2.4+   — Microservice instances and ACA infrastructure IPs

10.2.4.0/24   — appService
10.2.5.0/24   — functionApps

10.2.6.0/24   — privateEndpoints
  10.2.6.4    — SQL private endpoint NIC
  10.2.6.5    — Redis private endpoint NIC
  10.2.6.6    — Service Bus private endpoint NIC
  10.2.6.7    — Key Vault private endpoint NIC
  10.2.6.8    — ACR private endpoint NIC
  10.2.6.9    — Blob Storage private endpoint NIC
  10.2.6.10   — Cosmos DB private endpoint NIC (production only)

10.2.7.0/24   — sqlMi (reserved, unprovisioned)

Internal Documentation — Microtec Platform Team