Skip to content

Network isolation

Use private networking for production and workloads with sensitive data. Set NETWORK_ISOLATION=true explicitly before provisioning. The template's current default is false; that default is not the recommended production configuration.

Reserve public service endpoints for organization-approved, short-lived evaluations or demonstrations with synthetic or non-sensitive data. Public endpoints still require authentication and authorization, but those checks do not make them private. Do not disable isolation to work around connectivity or deployment failures.

This page explains connectivity, DNS and build requirements rather than deployment steps. How it works introduces the input formats and deployment lifecycle.

Both providers use the root main.parameters.json examples on this page. For Terraform, preprovision generates typed inputs automatically; see the Terraform input procedure.

A private endpoint gives a service a private IP address in a VNet. Private DNS directs its normal hostname to that address. A virtual private network (VPN) connects an authorized remote computer or network to the VNet.

A jumpbox is a virtual machine (VM) used for administration; Azure Bastion provides remote access to it. A NAT gateway provides outbound address translation. None of these connections grants permission to read service data.

With NETWORK_ISOLATION=true, Agent Landing Zone uses private endpoints and private DNS for the deployed workload services. With the default empty allowedIpRanges, public access to those service endpoints is disabled. Azure Resource Manager remains public; telemetry and optional public ingress have separate settings.

An explicit, nonempty allowedIpRanges in main.parameters.json enables IP-restricted public access on services that support those rules, even with isolation enabled. Those public paths and any reused network or DNS resources remain part of the connectivity design.

The Deploy infra only and Deploy full stack runbooks contain the procedures. The Azure DevOps runbook covers optional pipeline automation. Deployment choices explains standalone and hub integration. An AI Gateway governs model requests, not workload networking or user access. Private endpoints, DNS, routes, firewall rules and authorization remain necessary.

With the resource group destinations, locally owned private endpoints default to the resolved network group, which can differ from their services' groups. The explicit AZURE_PE_RESOURCE_GROUP_NAME override and existing-VNet/SIDE_BY_SIDE precedence in Deployment settings still apply.

Teams and Microsoft 365 Copilot publication

Publish to Teams and M365 adds a manual, source-IP-filtered public exception for the Foundry Activity route while Foundry and Bot Service public network access stays disabled. Microsoft calls this a source IP-filtered Activity Protocol public endpoint.

Channel messages use public HTTPS, not Private Link, so this path is not private end to end. If public agent ingress is prohibited, do not use that publication path. Other Foundry APIs remain private, and the template does not enable this exception.

The Connect Copilot Studio runbook describes an authenticated agent flow and Power Platform VNet delegation to reach the Foundry private endpoint; it does not require the Activity-route public exception.

What changes with isolation

Area NETWORK_ISOLATION=false NETWORK_ISOLATION=true
Workload service access Public endpoints, with service authentication and authorization Private endpoints by default
DNS Public DNS Private DNS zones linked to the VNet
Jumpbox, Azure Bastion, NAT gateway Not deployed by default Deployed by default
Container image builds Local Docker or regular ACR Tasks ACR Task agent pool inside the VNet by default
Post-provision and deploy Run from an authorized host that can reach the endpoints Run from an authorized host connected to the VNet

Note

The ACR Task agent pool is created only for isolated deployments. When isolation is off, supported components can build with local Docker or regular ACR Tasks. No pool is created, even if DEPLOY_ACR_TASK_AGENT_POOL is true.

Isolation and provisioning

NETWORK_ISOLATION=true is resolved before provisioning. The selected topology, subnet creation flags and resource ownership determine which subnets are created. Choose who manages them before first provision.

Choose subnet ownership

These choices apply with network isolation enabled. Hub connectivity and DNS remain separate decisions.

Network choice USE_EXISTING_VNET DEPLOY_SUBNETS Responsibility
New VNet and subnets false true The template creates the VNet and selected subnets.
Existing VNet, template-managed subnets true true Supply EXISTING_VNET_RESOURCE_ID; the template creates/updates selected subnets.
Existing VNet, externally managed subnets true false Supply the VNet ID; its owner prepares every subnet required by enabled consumers.

Using an existing VNet does not make deployment read-only. Individual creation flags can exclude subnets from template management. See the network selection examples.

Default subnets

The new VNet's default address space is 192.168.0.0/21. Names and ranges can be overridden using the subnet inputs.

Purpose Default name Default CIDR
Foundry Agent Service agent-subnet 192.168.0.0/24
Container Apps environment aca-environment-subnet 192.168.1.0/24
Foundry/grounding private endpoints pe-subnet 192.168.2.0/26
Bastion AzureBastionSubnet 192.168.2.64/26
Firewall AzureFirewallSubnet 192.168.2.128/26
VPN/ExpressRoute reservation GatewaySubnet 192.168.2.192/26
Application Gateway AppGatewaySubnet 192.168.3.0/27
Jumpbox jumpbox-subnet 192.168.3.64/27
Build agents devops-build-agents-subnet 192.168.3.96/27
Application private endpoints application-pe-subnet 192.168.3.128/26
Basic firewall management AzureFirewallManagementSubnet 192.168.3.192/26
Power Platform powerplatform-subnet 192.168.4.0/24
AI Gateway ai-gateway-subnet 192.168.5.0/24

Subnet delegations

  • Foundry Agent Service and Container Apps environment: Microsoft.App/environments.
  • Power Platform: Microsoft.PowerPlatform/enterprisePolicies.
  • AI Gateway: Microsoft.Web/serverFarms.
  • All other subnets in this plan: no delegation.

Firewall data subnet creation defaults to the local firewall requirement. The management subnet is used only by a standalone Basic firewall. GatewaySubnet is opt-in. The table is an address plan, not an unconditional resource inventory; shared-hub services do not require these reservations in the spoke.

Creation is not service selection. A false subnet creation flag does not disable its consumers: any enabled consumer still needs a valid subnet. With isolation off, no VNet or subnets are provisioned.

Prepared subnets are not deployed services. These reservations do not deploy APIM or VPN/ExpressRoute gateways, create a Power Platform enterprise policy, or associate a Power Platform environment. Those integrations need separate setup.

Enabled application Cosmos DB, Key Vault, App Configuration, Container Apps, ACR and Azure Monitor Private Link Scope endpoints use the application private endpoint subnet. Foundry/grounding endpoints use pe-subnet by default. Application endpoints never fall back to the Foundry subnet, including when application subnet creation is disabled. This separation is independent of resource group count.

Keep the reserved name GatewaySubnet; do not attach an NSG, default-route UDR or delegation to it. AI Gateway uses APIM Standard v2/Premium v2 outbound VNet integration, with a subnet of /27 or larger, delegated to Microsoft.Web/serverFarms and associated with an NSG. Preserve an outbound HTTPS path to Azure Key Vault. No reserved subnet name is required for APIM; do not place APIM private endpoints in its delegated integration subnet.

The Power Platform /24 is a capacity default, not a platform minimum. Size for environment demand: approximately 25–30 IPs per production environment or 6–10 per nonproduction environment, plus five subnet-reserved IPs. See Power Platform subnet sizing.

Azure Resource Manager (ARM) creates and manages Azure resources through a public control plane, but azd provision also runs lifecycle hooks. An existing environment can need private App Configuration access before ARM deployment to resolve its topology. Post-provision also needs private connectivity, so an unconnected host cannot complete every stage.

The matching deployment runbook therefore requires a connected host. The default Foundry hosted deployment automatically prepares its image and application handoff during azd deploy, as described in Deploy full stack.

Private network access

Private services can be reached through:

  • Point-to-site or site-to-site VPN into the landing zone VNet or a peered hub.
  • A VM or build agent in the VNet or a peered VNet, with private DNS zone access.
  • The jumpbox VM deployed by the landing zone, reached through Azure Bastion.

Jumpbox access

The default jumpbox is a Windows VM. Unless overridden, its administrator user is testvmuser. The password is supplied through the secure vmAdminPassword provisioning input, not a documented Key Vault secret. Unavailable credentials require an authorized administrator's approved reset procedure, without exposing passwords in shell history or logs.

Azure Bastion provides portal access to the VM. It still needs the deployment prerequisites. Docker is not installed by default and is unnecessary for ACR Task agent-pool builds.

Connected-host requirements

The connected host needs the same reviewed platform Git commit or release tag and approved inputs as the original workspace. Its local azd environment also needs current provisioning outputs. The Deploy infra only runbook explains environment selection, output refresh and separate provisioning/configuration steps.

The jumpbox's managed identity, an Azure-managed service identity that does not need a stored password, needs the selected application's configuration and build roles.

For hosted-agent authoring, the runner needs Foundry User on the exact Foundry project, plus read access to the Foundry account. Cognitive Services Contributor and OpenAI User alone do not grant the agent data-plane actions.

Subscription or resource-group Owner is not an appropriate fix for this denial. See Foundry RBAC for the current role catalog and scopes. New grants need time to propagate.

An infrastructure-only deployment stops after provisioning and post-provision configuration. It can contain placeholder Container Apps without running the selected applications. The Deploy full stack runbook also deploys application code.

Post-provision can be deferred

When isolation is enabled, post-provision can be deferred instead of failing. RUN_FROM_JUMPBOX=false (or 0, no, skip) requests deferral, as does AZURE_SKIP_NETWORK_ISOLATION_WARNING=true while RUN_FROM_JUMPBOX is not truthy. A truthy RUN_FROM_JUMPBOX, such as true, requests the connectivity check even if the warning flag is set. Deferral produces:

Post-provision configuration explicitly deferred; application setup is incomplete.

If the other provisioning stages succeed, azd provision reports success, but the application is not configured. Deferral does not bypass earlier topology or provisioning checks. Configuration remains incomplete until deferral is cleared and configuration succeeds from a connected host. The Deploy infra only runbook provides those steps.

When the deferral settings are not set and the private endpoints cannot be reached, post-provision fails with:

Private post-provision prerequisites failed. Connect through VPN/VNet and rerun postProvision; configuration has not started.

Warning

RUN_FROM_JUMPBOX only controls whether post-provision is deferred. It does not provide connectivity. azd deploy always checks private reachability, and fails with "Private deployment prerequisites failed" when the host cannot reach the endpoints.

Image builds in isolated deployments

Public build agents cannot reach the default private registry. Remote builds use an ACR Task agent pool inside the VNet (DEPLOY_ACR_TASK_AGENT_POOL=true). Hosted topology composition selects this pool when network isolation is enabled.

If the pool is missing, azd deploy stops before building. Pool creation uses DEPLOY_ACR_TASK_AGENT_POOL=true through the matching deployment runbook. Where a component supports local builds, BUILD_MODE=local instead needs a VNet-connected host with working Docker.

The local alternative applies to component scripts that support BUILD_MODE=local. Automatic hosted orchestrator image preparation and isolated custom source builds still require the private pool. Supplying an already-built immutable digest can skip those builds. To deploy without a pool, the root pre-deploy check also requires BUILD_MODE=local. Each remaining service must support local builds for that exception to work.

Application-specific package feeds

The root deployment defaults include dependency-verified package feed destinations alongside common language and OS package registries, through the scoped infrastructure build-egress configuration. This is a build-only allowlist, not a runtime or general Internet exception. It does not allow every mirror recorded in a custom application's lockfile. The exact component commit's resolved URLs and download redirects determine its build needs.

Additional dependencies are declared in parameters.additionalAcrTaskBuildFqdns.value in the root main.parameters.json. This is an explicit array, not an azd environment variable. Provisioning applies it; the connected runner needs the same reviewed parameter file to preserve the setting on later provisions.

The Agent Application orchestrator frontend lockfile uses ms-feed-2.pkgs.visualstudio.com, ms-feed-12.pkgs.visualstudio.com, ms-feed-17.pkgs.visualstudio.com, and ms-feed-25.pkgs.visualstudio.com. Their public package downloads redirect to *.vsblob.vsassets.io. These four exact feeds and the redirect content delivery network (CDN) are included in the Agent Landing Zone default build allowlist. packages.microsoft.com is already included in the OS-package rule and does not need an additional entry.

With extendFirewallForAcrTaskBuilds=true (the default) and an effective ACR Task agent pool, the feeds, redirect CDN, and additional hosts are allowed only from the build-agent subnet over HTTPS on port 443. They are not added to jumpbox, application, or agent-subnet rules. The additional-host array defaults to empty.

Disabling the build-egress extension removes these package rules. Re-enabling it restores them. This egress rule has no DNS-proxy dependency and does not change client DNS.

Do not enable public registry access, allow all Internet egress, disable TLS verification, or change dependency integrity hashes to work around a failed build.

See Package installation fails inside the build pool for diagnosis.

Component runtime egress

Application components declare additional runtime destinations in components[].egress. The plan follows actual enabled workloads: optional ingestion, hosted or preserved Container App orchestration, and additive custom applications. The bundled UI needs no additional fixed destination. Both orchestrator and ingestion initialize tiktoken, whose empty-cache startup downloads encoding assets from openaipublic.blob.core.windows.net over HTTPS/443.

These are runtime rules, not build-feed rules or replacements for private endpoints, authentication, DNS or routing. Configured SharePoint, SQL, MCP and other custom destinations require their own dependency review.

Review before provisioning

From the platform root with the prepared Python environment, set the intended topology, ingestion selection and application definition in the selected azd environment, then run:

python -m config.deployment.egress --plan --environment <environment-name>

This reads the named local azd environment and validates declarations without Azure access. Review policyMode, selected components, destinations and purposes. The preprovision hook repeats this calculation, prints it and saves .azure/<environment-name>/component-egress-plan.json before foundation deployment. Approval of provisioning includes these declared requirements.

After infrastructure exists and local provisioning outputs are current, use:

python -m config.deployment.egress --review --environment <environment-name>

This is read-only. It resolves actual workload subnet prefixes and, for a deployment-managed policy, reports additions, updates and removals. A fresh deployment cannot resolve subnet prefixes until its infrastructure exists. Postprovision and predeploy print this resolved plan before managed reconciliation. If postprovision is explicitly deferred, reconciliation is also deferred; predeploy still enforces the connectivity and plan checks.

Policy ownership

Deployment Behavior
NETWORK_ISOLATION=false No component firewall reads or writes; declarations do not create a firewall
Isolated with a deployment-managed firewall Reconciles only marked application rules in AgentLzComponentEgress, priority 400
Isolated with an external firewall Reports required rules and components without egress declarations; never reads or mutates the external policy

For managed policies, the runner needs management-plane subnet reads and Microsoft.Network/firewallPolicies/ruleCollectionGroups/read and write on the deployment policy. The reconciler does not write the parent policy. For external policies, the network owner compares the report with their own policy and applies approved changes. Reporting does not prove that egress is allowed.

Shared destination/protocol/port tuples produce one rule, with sources and ownership combined across components. Removing one owner narrows sources where possible; the rule remains until its final declared owner disappears.

Enabled components without declarations retain their owned requirements. Other rules and collections, including unmarked entries inside the component group, are preserved. Ownership collisions, malformed marked rules, conflicting priorities or concurrent changes fail rather than being silently adopted or overwritten.

Source scope and recovery

Rules use the actual provisioned Container Apps or Foundry agent subnet prefixes, including existing-VNet selections, not the whole VNet or *. Subnet scope is not component isolation: every workload sharing a source subnet can use its union of allowed destinations. Existing platform rules can also allow traffic. Use dedicated subnets or environments and an approved network design when workloads need distinct egress boundaries.

After changing declarations or selections, review the new local plan and run the normal provisioning sequence before deploying. A missing or stale saved plan stops apply before Azure access. Do not copy a plan or provisioning outputs from another environment.

For rollback, first review explicit empty declarations for the components whose additional rules should be removed, then reconcile using the current hooks. Keep declarations for any remaining consumers. Only afterward roll back hooks or metadata: reverting code alone does not remove existing rules. Never delete shared foundation groups or externally managed policy content.

Private connectivity checks

The runbooks check service hostnames from the deployment runner, including the host in APP_CONFIG_ENDPOINT:

Check Expected result Meaning
DNS Only private IPv4 addresses (10.x, 172.16 through 31.x or 192.168.x) The runner resolves the private endpoint rather than the public endpoint.
Transmission Control Protocol (TCP) Connection succeeds on port 443 Routing and firewall policy allow the endpoint connection.
TLS Handshake succeeds with the original hostname and normal certificate validation The connection reaches the expected service securely.

Public DNS answers usually indicate a missing private-zone link or an incorrect VPN/hub forwarding path.

On Windows, nslookup can differ from the operating system resolver used by the Python prerequisite check, especially with VPN Name Resolution Policy Table (NRPT) rules. That check requires private IPv4 answers and rejects mixed public/private, IPv6, loopback and link-local answers.

It then verifies TCP 443 and TLS without sending an HTTP request or credentials. Connectivity is not authorization: API access and document permissions still need tests with the intended user identities.

Firewall SKU and management networking

New isolated standalone deployments select AZURE_FIREWALL_SKU=Basic. Select Standard explicitly when DNS proxy, network-rule FQDN filtering or greater capacity is required. Basic supports application HTTP(S) FQDN rules and IP/service-tag network rules; assess its approximately 250 Mbps capacity class against build, image-download and ingestion peaks.

Topology Local firewall data subnet/IP Local management subnet/IP GatewaySubnet
Standalone Basic Required Required Explicit reservation only
Standalone Standard Required None Explicit reservation only
External hub, with or without gateway No IP; data subnet only if explicitly reserved None Explicit local reservation only
Public/non-isolated None None None

Both local SKUs use AzureFirewallSubnet. Basic additionally needs the exact name AzureFirewallManagementSubnet, a /26-or-larger range and a separate Standard/static public IP and management NIC configuration. Keep management networking free of generic NSGs, workload default routes, NAT, delegations and service endpoints. Validate externally managed subnet routing with the network owner. Workload routes use the data-plane private IP.

For external hub egress, explicitly disable local firewall deployment and configure the approved external next hop or route table. A deployment-mode label alone does not configure egress or change hub resources.

Opt-in firewall DNS proxy

ENABLE_FIREWALL_DNS_PROXY defaults to false and maps to the Bicep boolean enableFirewallDnsProxy (also default false), which sets dnsSettings.enableProxy on a Standard firewall. Basic with proxy enabled is rejected; its policy omits DNS settings. It applies only when the deployAzureFirewall and networkIsolation gates enable firewall deployment. It is intended for a topology that deliberately uses the firewall as its DNS forwarding path. The matching deployment runbook applies the selection through normal provisioning.

Enabling the proxy does not redirect VNet or VPN clients to the firewall or rewrite their DNS configuration. It is independent of the build-feed egress allowlist.

Client DNS routing and private-zone resolution remain separate requirements. A proxy cannot repair missing zone links, VPN routes or application authentication. Disabling it requires confirmation that the deployed DNS path does not depend on it before reprovisioning.

Private native Blob ingestion

For the default native Blob path, Search reads and processes Blob documents for Foundry IQ retrieval. A searchIndex source instead exposes an index populated by another pipeline. Their private-network setup differs.

Native azureBlob ingestion uses outbound shared private links managed by Search. Configuration verifies deployment-owned links, targets and groups before dependent cleanup/mutation and again before knowledge source creation. It does not automatically approve target connections. Pending links require approval by an authorized target administrator for each connection.

The gate is limited to NETWORK_ISOLATION=true, RETRIEVAL_BACKEND=foundry_iq and rendered native azureBlob sources, excluding the searchIndex pattern. It checks the Agent Application Search link to deployment Blob storage (blob) and the links to the deployment Foundry account (openai_account, foundry_account, cognitiveservices_account). It does not configure the separate Foundry Search service or unrelated services.

Exact names come from the template's SEARCH_SHARED_PRIVATE_LINKS manifest, including bounded Foundry names. The exact Search shared-link GET must return the expected name, target and group. If its body includes a resource ID, that must match too.

The target service receives a private endpoint connection (PEC) request. Because its name, message and endpoint ID may not identify the originating Search link, an administrator must verify and approve the correct request. The configuration script reads the deployment's Search links and leaves target-side approval to that administrator. See Microsoft's approval and shared-link status procedure, sections 2 and 3.

A Pending source link stops immediately with its exact Search ID, target ID, group and link name for administrator investigation and approval. After approval, configuration needs another run. Each source link must report connection status Approved and provisioning state Succeeded before configuration continues. Read timeouts or denials require restored connectivity or Search read permissions, not public access. See Search shared private links are not ready.

Polling has a 600-second total readiness budget, a 10-second interval and ARM request timeouts of at most 30 seconds (limited by the remaining budget). Each exact Search shared link must be Approved and Succeeded, the documented source-side readiness signal. Approved links whose provisioning is still propagating use bounded polling. Pending approval does not spend this budget waiting for an unprovable target match.

Administrator-approved links are usable even when target PECs are paginated, opaque or unreadable by the runner. The existing Azure CLI/managed-identity credential is reused. The runner needs Search shared-link read permission, with no new secret, target PEC read/write requirement or automatic RBAC grant.

Native ingestion supports configured Foundry IQ source kinds and is not feature-equivalent to Agent App Ingestion. Choosing it does not remove Entra ID authentication, on-behalf-of (OBO) token exchange, RBAC or document-level authorization. OBO exchanges a user's token for another API's token while retaining that user's delegated identity.

Azure Data Lake Storage (ADLS) Gen2 uses Blob storage with a hierarchical directory namespace. In particular, FOUNDRY_IQ_INGESTION_PERMISSION_OPTIONS=[] is a deliberate shared-source metadata choice for active, supported non-ADLS native Blob ingestion, not a workaround for a private connection failure.

Infrastructure-published [] for ai_search (any pattern) or foundry_iq / searchIndex is accepted as unused metadata, not a shared-source opt-in: no native Blob source is rendered. See Explicit shared-source permission options.

Integrate with an existing hub

Hub integration uses DEPLOYMENT_MODE=ailz-integrated with explicit settings:

Setting Purpose
DEPLOYMENT_MODE=ailz-integrated Declares integration intent; does not attach a hub or override component flags by itself
HUB_INTEGRATION_HUB_VNET_RESOURCE_ID Hub VNet to peer with
HUB_INTEGRATION_CREATE_HUB_PEERING Create spoke-to-hub peering for a new spoke VNet (default true); hub owner supplies reverse peering. Existing VNet peerings are externally managed
HUB_INTEGRATION_PEERING_ALLOW_GATEWAY_TRANSIT Allow gateway transit (default false)
HUB_INTEGRATION_PEERING_USE_REMOTE_GATEWAYS Use the hub gateway (default false)
HUB_INTEGRATION_EGRESS_NEXT_HOP_IP Next hop for egress, for example the hub firewall
HUB_INTEGRATION_EXISTING_ROUTE_TABLE_RESOURCE_ID Existing route table to attach
AZURE_PE_RESOURCE_GROUP_NAME, AZURE_PE_LOCATION Where to place private endpoints
EXISTING_* Reuse the existing VNet, private DNS zones, jumpbox, Bastion, NAT gateway or monitoring resources

Deployment settings lists the inputs; hub-and-spoke design explains their network effects. Execution steps belong to the Deploy infra only runbook.

© 2026 Azure AI Landing Zones