Skip to content

Private Endpoints

Sam Betts edited this page May 5, 2026 · 10 revisions

This is optional

If you need to ensure that all endpoints are private, you can integrate with a virtual network and restrict access to each resource via the same VNet.

Example network:

The resources in Azure should be accessible only via private IP addresses, accessible optionally via another private, on-premises network.

Automated Setup (Installer)

The installer now supports private VNet configuration out of the box. When the Networking option is enabled in the installer UI, the following is set up automatically:

What the Installer Creates

  1. Virtual Network (VNet) with a configurable subnet
  2. Private Endpoints for all PaaS resources:
    • SQL Server (pe-{name}-sql, group: sqlServer)
    • App Service (pe-{name}-app, group: sites)
    • Redis Cache (pe-{name}-redis, group: redisCache)
    • Storage Account (pe-{name}-blob, group: blob)
    • Key Vault (pe-{name}-vault, group: vault)
    • Service Bus (pe-{name}-sb, group: namespace)
    • Cognitive Services (pe-{name}-cognitive, group: account) - if enabled
  3. Private DNS Zones with VNet links and PE zone groups for automatic DNS resolution:
    • privatelink.database.windows.net (SQL)
    • privatelink.azurewebsites.net (App Service)
    • privatelink.redis.cache.windows.net (Redis)
    • privatelink.blob.core.windows.net (Storage)
    • privatelink.vaultcore.azure.net (Key Vault)
    • privatelink.servicebus.windows.net (Service Bus)
    • privatelink.cognitiveservices.azure.com (Cognitive Services)
  4. SKU enforcement for VNet compatibility:
    • Redis: upgraded to Standard (Basic does not support private endpoints)
    • Service Bus: created at Premium tier (private endpoints require Premium). Existing non-Premium namespaces cannot be upgraded in-place; the installer will log an error with a link to the migration documentation
    • SQL: upgraded to S2 if currently Basic
  5. App Service configuration for private DNS resolution:
    • WEBSITE_VNET_ROUTE_ALL = 1 - routes all outbound traffic through the VNet
    • WEBSITE_DNS_SERVER = 168.63.129.16 - uses Azure DNS for private DNS zone resolution

What You Still Need to Do Manually After the Installer

The installer does not handle the following steps, which must be completed manually:

  1. App Service outbound VNet integration - In the App Service networking blade, configure "VNet integration" to connect the app service to a subnet for outbound traffic. Without this, the WEBSITE_VNET_ROUTE_ALL setting has no effect. See the manual guide below.
  2. Storage Account table endpoint - The installer creates a private endpoint for blob storage only. If your workload accesses Azure Table Storage, you need to create an additional private endpoint for the table sub-resource manually. See Storage Account.
  3. Disable public access on individual resources (SQL, Redis, Storage, Key Vault, etc.) - The installer creates private endpoints but does not disable public network access on the resources.
  4. Application Insights & Log Analytics - Private link scope configuration for monitoring. See Application Insights and Log Analytics.
  5. Disable call imports - Webhook-based call tracking does not work with private endpoints. See Disable Call Imports.
  6. Power BI - If using PBI reports with private SQL. See Power BI Service.

Hybrid Worker VM Requirements

When VNet is enabled, the installer also configures an Azure Automation Hybrid Worker Group so that automation runbooks can execute within the private network. The installer automatically:

  • Creates a hybrid worker group in the Automation Account
  • Installs the HybridWorkerForWindows VM extension on the specified VM
  • Registers the VM as a hybrid worker with the Automation Account

VM prerequisites for the hybrid worker:

Requirement Details
Operating System Windows Server 2016 or later (64-bit)
PowerShell PowerShell 7.2 or later must be installed on the VM (download)
.NET Framework .NET Framework 4.6.2 or later
Network The VM must be connected to the same VNet (or a peered VNet) used by the private endpoints
Outbound connectivity The VM needs outbound HTTPS (443) access to Azure Automation endpoints and Azure AD for registration

Note: The hybrid worker extension installation is treated as non-fatal by the installer. If it fails (e.g. the VM is unreachable or missing prerequisites), the rest of the installation will continue. You can verify the extension status in the Azure portal under Virtual Machine → Extensions + applications and retry manually if needed.

For full details on hybrid worker requirements, see the Azure Automation Hybrid Runbook Worker documentation.

Limitations

In this mode, the system does have some limitations around data collection and configuration.

  • Due to how calls are tracked with Graph pushing notifications to the app service, this won't be possible with a privately protected endpoint.

The lack of calls can be mitigated if the only app service has a public endpoint, but assuming that too is private, it's impossible to receive webhook notifications from Graph API for calls and therefore we can't log call data.


Manual Setup Guide

The following sections describe how to configure private endpoints manually, either as an alternative to the installer or to complete the steps the installer does not cover.

VNet Configuration

For these steps to work, we need a virtual network (VNet) pre-configured with x2 subnets - a default one and then one for app services.

A screenshot of a phone Description automatically generated

All the dependencies will use the default subnet, and the app service will integrate with a second one.

Private endpoints are created on the VNet and add DNS zones for each resource as needed, so that each service has a private, internal IP address.

Example: for App Insights, when we create the endpoint, we get a new network interface card for it with a private IP address (10.0.0.X) + a DNS "westeurope-5.in.ai.privatelink.monitor.azure.com" (same as the public address).

A blue screen with white text Description automatically generated

In this case, the browser will now route requests to the private address, will pass internally to the App Insights instance and therefore be accepted.

In our example we're using Azure DNS, so resource name registration happens automatically.

A screenshot of a computer Description automatically generated

Your own infrastructure may have different requirements.

Important: if you have your own DNS infrastructure to integrate with, please add verification steps for each Azure service added below.

Configure Services for Private Access Only

In this guide, we assume that you have a working system created by either the installer or the manual configuration method.

Note: If you used the installer with VNet enabled, private endpoints and DNS zones for the services below (SQL, App Service, Redis, Storage, Key Vault, Service Bus, Cognitive Services) are already created. You may still need to disable public access on each resource and complete the App Service VNet integration step.

App Service

Add a private endpoint so access to it is restricted. In the "networking" blade of the app service:

A screenshot of a computer Description automatically generated

https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-overview

Next, we need to integrate the app service into our VNet so the web-jobs can access private resources. Back in the networking blade click "VNet integration"

A screenshot of a computer Description automatically generated

A screenshot of a computer Description automatically generated

Important: This outbound VNet integration step is required even when using the installer. The installer creates the private endpoint (inbound) and sets the WEBSITE_VNET_ROUTE_ALL and WEBSITE_DNS_SERVER app settings, but does not yet configure the outbound VNet integration.

VNet Integration Subnet Requirement

App Service VNet integration requires a dedicated subnet delegated to Microsoft.Web/serverFarms. You cannot use the same subnet that contains your private endpoints or VMs. If your VNet only has a single default subnet, you must create an additional subnet for integration:

az network vnet subnet create \
  --resource-group <your-rg> \
  --vnet-name <your-vnet> \
  --name app-integration \
  --address-prefixes 10.0.1.0/24 \
  --delegations Microsoft.Web/serverFarms

A /28 is the minimum size, but /24 is recommended. Once created, select this subnet when configuring VNet integration on the App Service.

Troubleshooting: If you disable public access on Service Bus (or other resources) and the App Service returns 401 - IP has been prevented to connect to the endpoint, this means the App Service is still routing traffic via its public IP. Verify:

  1. VNet integration is configured with the dedicated subnet above
  2. Route All is enabled (WEBSITE_VNET_ROUTE_ALL = 1)
  3. The privatelink.servicebus.windows.net (or relevant) private DNS zone is linked to the VNet used by the App Service integration

You can confirm DNS resolution from the App Service using Kudu console: nameresolvercli <namespace>.servicebus.windows.net — it should return the private IP (e.g. 10.0.0.x), not a public IP.

Now, any HTTP calls from outside the private network will not arrive at the app service.

SQL Server

Restrict public access and enable a private endpoint.

A screenshot of a computer Description automatically generated

A screenshot of a computer Description automatically generated

This will create a network interface for the private endpoint:

A screenshot of a computer Description automatically generated

Select the same VNet.

A screenshot of a computer Description automatically generated

You may wish to create a specific IP address. We're going for automatic configuration.

A screenshot of a computer Description automatically generated

Now, apps need to use this internal address to connect to any database on this server.

Redis Cache

A similar setup with Redis is needed.

Note: Redis requires at least Standard SKU for private endpoint support. The installer enforces this automatically.

https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-private-link

A screenshot of a computer Description automatically generated

A screenshot of a computer Description automatically generated

A screenshot of a computer Description automatically generated

Service Bus

Private endpoints and network isolation require a Premium tier service-bus.

Note: The installer creates new Service Bus namespaces at Premium tier when VNet is enabled. However, existing non-Premium namespaces cannot be upgraded in-place - Azure does not support this. The installer will log an error with a link to the migration documentation. You will need to create a new Premium namespace and migrate manually.

A screenshot of a computer Description automatically generated

The service bus created by default (without VNet) is a basic tier one, so we need to migrate through the standard tier too:

Screens screenshot of a screenshot of a screenshot Description automatically generated

...meaning we need to create a standard tier namespace, and also a premium one.

A yellow and purple text Description automatically generated

A screenshot of a computer Description automatically generated

Once your options are configured, you can start the migration from basic to premium.

A screenshot of a computer screen Description automatically generated

Once done we can create private endpoints as before:

A screenshot of a computer Description automatically generated

As before this will create a network interface in the selected VNet + register with DNS if managed by Azure.

Storage Account

For storage, we need to configure private endpoints for table + blob services.

Note: The installer creates a private endpoint for blob storage only. If your workload uses Azure Table Storage, you need to create an additional private endpoint for the table sub-resource manually.

A screenshot of a computer Description automatically generated

Enable private endpoints for blob & table storage.

A screenshot of a computer Description automatically generated

Ensure the right sub-resource is selected.

A screenshot of a computer Description automatically generated

DNS configuration is done if managed by Azure. Manual configuration will be needed if DNS is handled by your own infrastructure.

A screenshot of a computer Description automatically generated

Repeat the same for blob storage.

Key Vault

The installer creates a private endpoint for Key Vault automatically. To disable public access, go to the Key Vault networking blade and set "Allow access from" to "Private endpoint only".

Note: If public access is disabled before the installer finishes adding secrets, the installer will log an error (HTTP 403) and continue. You can add secrets manually afterwards from within the VNet.

Optional: Language Service

Language service is optionally used for Teams channel sentiment analysis and other areas of M365. If your configuration doesn't include this, you don't need to follow this step.

A screenshot of a computer Description automatically generated

Disable public access and save changes.

A screenshot of a computer Description automatically generated

There's only one sub-resource:

A screenshot of a computer Description automatically generated

Configure how you want the endpoint to appear on the VNet:

A screenshot of a computer Description automatically generated

Specify DNS

A screenshot of a computer Description automatically generated

No changes should be needed for configuration thanks to the CNAME above mapping the public DNS to the private DNS.

Application Insights

Note: Application Insights private link scope is not configured by the installer and must be set up manually.

Access to App Insights ingestion and tracking is limited via "Azure Monitor Private Link Scopes" on the "Network Isolation" blade.

A screenshot of a web page Description automatically generated

Create new:

A screenshot of a computer Description automatically generated

Add a network interface for private endpoint scope: A screenshot of a computer Description automatically generated

A screenshot of a computer Description automatically generated

Configure DNS. There are a few services that App Insights need to have DNS for:

A screenshot of a computer Description automatically generated

One the scope & endpoint are added, you can configure Application Insights to use them.

A screenshot of a computer Description automatically generated

With public-network ingestion disabled, any attempts to log data will be denied. Here's an example response:

A computer screen shot of a program code Description automatically generated

Equally with reading the data:

A close-up of a document Description automatically generated

You can only now read/write telemetry data from a device on the same VNet.

Log Analytics

Configure the workspace in the same way as Application Insights.

A screenshot of a computer Description automatically generated

Important: if you don't configure log analytics with the same Azure Monitor Private Link Scope, no telemetry data will be readable.

Configure App Services

Once components have been configured, the app service configuration will need to be updated.

Note: If you used the installer with VNet enabled, the app settings WEBSITE_VNET_ROUTE_ALL and WEBSITE_DNS_SERVER are already configured. The connection strings (SQL, Redis, Storage, Service Bus) use the standard public DNS names which automatically resolve to private IPs via the private DNS zones. No manual connection string changes are needed in that case.

Disable Call Imports

As public endpoints are needed for webhooks and this is precisely what we've disabled, we should stop the solution from even trying to setup the webhook as it will fail and generate errors.

In the app-services configuration, disable the calls import:

A screenshot of a computer Description automatically generated

Save changes.

App Service Settings for VNet DNS Resolution

When using private endpoints, the app service must route outbound traffic through the VNet so that private DNS zones resolve correctly. The installer sets these automatically, but if configuring manually, add the following app settings:

Setting Value Purpose
WEBSITE_VNET_ROUTE_ALL 1 Routes all outbound traffic through the VNet (not just RFC1918)
WEBSITE_DNS_SERVER 168.63.129.16 Uses Azure-provided DNS which resolves private DNS zones

These settings require the app service to have outbound VNet integration configured (see App Service above).

Change SQL Connection

Note: If the installer created the environment with VNet enabled, the SQL connection string already uses the standard FQDN (e.g., myserver.database.windows.net) which resolves to the private IP via the privatelink.database.windows.net DNS zone. No manual change is needed — skip to the next section.

The following applies only when converting an existing (non-VNet) deployment to use private endpoints. Once you disable public network access on the SQL server, the web-jobs will crash with this error:

SqlException: Reason: An instance-specific error occurred while establishing a connection to SQL Server. Connection was denied since Deny Public Network Access is set to Yes. To connect to this server, use the Private Endpoint from inside your virtual network.

In the app services configuration, change the SQL connection DNS:

A screenshot of a computer Description automatically generated

Check app-service web job logs from a virtual machine on same VNet:

A screenshot of a computer Description automatically generated

Verify web-jobs are running:

A screenshot of a web jobs application Description automatically generated

Both web-jobs should be in the "running" state, without restarts.

Redis

Redis doesn't require a connection string change as a CNAME record is added so, in my example, "advanalyticsdev.redis.cache.windows.net" points to "advanalyticsdev.privatelink.redis.cache.windows.net", which is pointed at the local VNet IP address.

This means that no changes should be needed for the app-service to work with the old, public DNS.

Service Bus

Equally the service-bus DNS should still work for the same reasons.

Power BI Service (Optional)

The Power BI service will need to access the private endpoint for SQL if you're using PBI reports - https://learn.microsoft.com/en-us/power-bi/enterprise/service-security-private-links

Clone this wiki locally