Appearance
Subnets
Each Microtec ERP environment VNet is divided into seven subnets with distinct purposes, NSG profiles, and service delegation requirements.
Subnet Overview Table
| Subnet Name | CIDR Suffix | Size | Purpose | Services |
|---|---|---|---|---|
| gatewaySubnet | .0.0/27 | 32 IPs | VPN/ExpressRoute gateway | Azure VPN Gateway (reserved) |
| publicApps | .1.0/24 | 256 IPs | Internet-facing Container Apps | Gateway.API, Keycloak |
| privateApps | .2.0/23 | 512 IPs | VNet-internal Container Apps | All other microservices |
| appService | .4.0/24 | 256 IPs | App Service VNet integration | App Service instances |
| functionApps | .5.0/24 | 256 IPs | Function App VNet integration | Azure Functions |
| privateEndpoints | .6.0/24 | 256 IPs | PaaS private endpoints | SQL, Redis, Service Bus, Storage, KV, ACR |
| sqlMi | .7.0/24 | 256 IPs | Reserved for SQL Managed Instance | SQL 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
| Service | Internal Port | Public Port |
|---|---|---|
| Gateway.API | 80 | 443 (via Front Door) |
| Keycloak | 8080 | 443 (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 allImportant: Inbound HTTPS should only be allowed from
AzureFrontDoor.Backendservice tag, not fromInternetdirectly. 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.WorkermTLS 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 allSubnet 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
| Service | Private DNS Zone | Approx IP (dev) |
|---|---|---|
| Azure SQL Server | privatelink.database.windows.net | 10.0.6.4 |
| Redis Cache | privatelink.redis.cache.windows.net | 10.0.6.5 |
| Service Bus | privatelink.servicebus.windows.net | 10.0.6.6 |
| Key Vault | privatelink.vaultcore.azure.net | 10.0.6.7 |
| ACR | privatelink.azurecr.io | 10.0.6.8 |
| Blob Storage | privatelink.blob.core.windows.net | 10.0.6.9 |
| Cosmos DB (prod) | privatelink.mongo.cosmos.azure.com | 10.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 outboundSubnet 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)