From 95bb7f9370f06e9f5d4419e2841fca0bad589d94 Mon Sep 17 00:00:00 2001 From: Paul Yuknewicz Date: Wed, 1 Apr 2026 10:35:58 -0700 Subject: [PATCH 01/20] feat(operate): App Service SKU selection, custom domains, networking (Gap-5) Closes #1613 | Parent: #1608 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../services/app-service/custom-domains.md | 150 ++++++++++++++++++ .../services/app-service/networking.md | 141 ++++++++++++++++ .../services/app-service/sku-selection.md | 115 ++++++++++++++ 3 files changed, 406 insertions(+) create mode 100644 plugin/skills/azure-prepare/references/services/app-service/custom-domains.md create mode 100644 plugin/skills/azure-prepare/references/services/app-service/networking.md create mode 100644 plugin/skills/azure-prepare/references/services/app-service/sku-selection.md diff --git a/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md b/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md new file mode 100644 index 000000000..eb32ec482 --- /dev/null +++ b/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md @@ -0,0 +1,150 @@ +# App Service Custom Domains and Managed TLS + +## Prerequisites + +| Requirement | Details | +|------------|---------| +| SKU tier | Basic (B1) or higher | +| DNS access | Ability to create CNAME, A, and TXT records | +| Domain ownership | Verified via TXT record | + +## DNS Configuration + +### Subdomain (CNAME) + +| Record Type | Name | Value | +|------------|------|-------| +| CNAME | `www` | `.azurewebsites.net` | +| TXT | `asuid.www` | `` | + +### Apex / Root Domain (A Record) + +| Record Type | Name | Value | +|------------|------|-------| +| A | `@` | `` | +| TXT | `asuid` | `` | + +Get the verification ID and IP address: + +```bash +# Get verification ID +az webapp show -n $APP -g $RG --query "customDomainVerificationId" -o tsv + +# Get IP address (for A records) +az webapp show -n $APP -g $RG --query "inboundIpAddress" -o tsv +``` + +> 💡 **Tip:** Prefer CNAME records for subdomains. For apex domains, consider using an Azure DNS alias record to avoid hardcoding IP addresses that may change. + +## Bind Custom Domain via CLI + +```bash +# Add custom domain +az webapp config hostname add -n $APP -g $RG --hostname www.contoso.com + +# Create managed certificate (free) +az webapp config ssl create -n $APP -g $RG --hostname www.contoso.com + +# Bind the certificate +az webapp config ssl bind -n $APP -g $RG \ + --certificate-thumbprint $THUMBPRINT --ssl-type SNI +``` + +## Bicep — Custom Domain with Managed Certificate + +```bicep +resource customDomain 'Microsoft.Web/sites/hostNameBindings@2022-09-01' = { + parent: webApp + name: 'www.contoso.com' + properties: { + siteName: webApp.name + hostNameType: 'Verified' + sslState: 'Disabled' // enable after cert is created + } +} + +resource managedCert 'Microsoft.Web/certificates@2022-09-01' = { + name: 'www.contoso.com' + location: location + properties: { + serverFarmId: appServicePlan.id + canonicalName: 'www.contoso.com' + } + dependsOn: [customDomain] +} +``` + +> ⚠️ **Warning:** Managed certificate creation requires the DNS records to be in place first. The hostname binding must exist before requesting the certificate. + +## Terraform — Custom Domain with Managed Certificate + +```hcl +resource "azurerm_app_service_custom_hostname_binding" "domain" { + hostname = "www.contoso.com" + app_service_name = azurerm_linux_web_app.app.name + resource_group_name = azurerm_resource_group.rg.name +} + +resource "azurerm_app_service_managed_certificate" "cert" { + custom_hostname_binding_id = azurerm_app_service_custom_hostname_binding.domain.id +} + +resource "azurerm_app_service_certificate_binding" "binding" { + hostname_binding_id = azurerm_app_service_custom_hostname_binding.domain.id + certificate_id = azurerm_app_service_managed_certificate.cert.id + ssl_state = "SniEnabled" +} +``` + +## TLS Options + +| Option | Cost | Renewal | Use Case | +|--------|------|---------|----------| +| App Service Managed Certificate | Free | Auto-renewed | Standard custom domains | +| App Service Certificate (purchased) | ~$70/yr | Auto-renewed | Extended validation, wildcard | +| Bring your own certificate | Varies | Manual | Enterprise PKI, specific CA | + +### Enforce HTTPS Only + +```bicep +resource webApp 'Microsoft.Web/sites@2022-09-01' = { + name: appName + location: location + properties: { + httpsOnly: true + // ... + } +} +``` + +```hcl +resource "azurerm_linux_web_app" "app" { + name = var.app_name + # ... + https_only = true +} +``` + +## Minimum TLS Version + +```bash +# Set minimum TLS version to 1.2 +az webapp config set -n $APP -g $RG --min-tls-version 1.2 +``` + +```bicep +siteConfig: { + minTlsVersion: '1.2' +} +``` + +> ⚠️ **Warning:** TLS 1.0 and 1.1 are deprecated. Always set minimum TLS version to 1.2 for production workloads. + +## Troubleshooting + +| Issue | Cause | Fix | +|-------|-------|-----| +| Domain verification fails | Missing TXT record | Add `asuid` TXT record and wait for DNS propagation | +| Certificate creation fails | DNS not yet propagated | Wait 5-15 min for propagation; verify with `nslookup` | +| SSL binding error | SKU too low | Upgrade to Basic (B1) or higher | +| Managed cert not renewing | DNS record changed | Verify CNAME/A record still points to the app | diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md new file mode 100644 index 000000000..12ad438a2 --- /dev/null +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -0,0 +1,141 @@ +# App Service Networking + +VNet integration, Private Endpoints, Access Restrictions, and Hybrid Connections. + +## Feature Availability by SKU + +| Feature | Free/Basic | Standard | Premium | Isolated | +|---------|:-:|:-:|:-:|:-:| +| VNet integration (outbound) | ❌ | ✅ | ✅ | ✅ (native) | +| Private Endpoints (inbound) | ❌ | ❌ | ✅ | ✅ | +| Access Restrictions | ✅ | ✅ | ✅ | ✅ | +| Hybrid Connections | ❌ | 25 | 200 | 200 | +| Service Endpoints | ❌ | ✅ | ✅ | ✅ | + +## VNet Integration (Outbound) + +Routes outbound traffic from the app through a VNet subnet, enabling access to private resources (databases, storage, VMs). + +### Subnet Requirements + +| Requirement | Value | +|------------|-------| +| Minimum subnet size | `/26` (64 addresses) recommended | +| Delegation | `Microsoft.Web/serverFarms` | +| Dedicated | One subnet per App Service plan | + +### Bicep — VNet Integration + +```bicep +resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' = { + parent: vnet + name: 'app-service-subnet' + properties: { + addressPrefix: '10.0.1.0/26' + delegations: [ + { + name: 'Microsoft.Web.serverFarms' + properties: { serviceName: 'Microsoft.Web/serverFarms' } + } + ] + } +} + +resource webApp 'Microsoft.Web/sites@2022-09-01' = { + name: appName + location: location + properties: { + serverFarmId: appServicePlan.id + virtualNetworkSubnetId: subnet.id + vnetRouteAllEnabled: true // route all outbound through VNet + } +} +``` + +> 💡 **Tip:** Set `vnetRouteAllEnabled: true` to route ALL outbound traffic through the VNet. Without this, only RFC1918 traffic is routed through the VNet. + +## Private Endpoints (Inbound) + +Expose the app on a private IP address within your VNet. Public access can be disabled entirely. + +### Bicep — Private Endpoint + +```bicep +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-11-01' = { + name: '${appName}-pe' + location: location + properties: { + subnet: { id: privateEndpointSubnet.id } + privateLinkServiceConnections: [ + { + name: '${appName}-connection' + properties: { + privateLinkServiceId: webApp.id + groupIds: ['sites'] + } + } + ] + } +} + +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azurewebsites.net' + location: 'global' +} + +resource dnsLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { + parent: privateDnsZone + name: '${vnet.name}-link' + location: 'global' + properties: { + virtualNetwork: { id: vnet.id } + registrationEnabled: false + } +} +``` + +> ⚠️ **Warning:** Private Endpoints require Premium (P1v3+) or Isolated tier. The private DNS zone `privatelink.azurewebsites.net` must be linked to the VNet for name resolution. + +## Access Restrictions + +Control inbound access with IP-based or service-tag rules. Available on all SKUs. + +### Bicep — Access Restrictions + +```bicep +siteConfig: { + ipSecurityRestrictions: [ + { + name: 'allow-office' + priority: 100 + action: 'Allow' + ipAddress: '203.0.113.0/24' + } + { + name: 'deny-all' + priority: 2147483647 + action: 'Deny' + ipAddress: 'Any' + } + ] + scmIpSecurityRestrictionsUseMain: true +} +``` + +> 💡 **Tip:** Always restrict the SCM/Kudu site too. Use `scmIpSecurityRestrictionsUseMain: true` to inherit main site rules, or define separate SCM rules. + +## Hybrid Connections + +Connect to on-premises resources without VPN. Requires Standard tier or higher. Uses Hybrid Connection Manager (HCM) agent on-premises relaying through Azure Relay. + +> ⚠️ **Warning:** Each Hybrid Connection maps to a single host:port endpoint. Standard tier supports 25; Premium/Isolated support 200. + +## Troubleshooting + +| Issue | Cause | Fix | +|-------|-------|-----| +| Cannot reach private DB | VNet integration not enabled | Enable VNet integration; check `vnetRouteAllEnabled` | +| DNS resolution fails | Private DNS zone not linked | Link `privatelink.*` DNS zone to VNet | +| Access restriction not working | Priority ordering wrong | Lower numbers = higher priority; check rule order | +| Hybrid Connection timeout | HCM not running | Verify HCM service status on-premises | +| Outbound traffic blocked | NSG rules on subnet | Allow outbound to required services in NSG | diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md new file mode 100644 index 000000000..1a0464896 --- /dev/null +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -0,0 +1,115 @@ +# App Service SKU Selection + +## SKU Comparison Matrix + +| Feature | Free (F1) | Basic (B1-B3) | Standard (S1-S3) | Premium (P1v3-P3v3) | Isolated (I1v2-I3v2) | +|---------|:-:|:-:|:-:|:-:|:-:| +| **Custom domains** | ❌ | ✅ | ✅ | ✅ | ✅ | +| **TLS/SSL bindings** | ❌ | ✅ (SNI) | ✅ (SNI + IP) | ✅ (SNI + IP) | ✅ (SNI + IP) | +| **Deployment slots** | ❌ | ❌ | 5 | 20 | 20 | +| **Auto-scale** | ❌ | ❌ | ✅ (10 inst.) | ✅ (30 inst.) | ✅ (100 inst.) | +| **VNet integration** | ❌ | ❌ | ✅ | ✅ | ✅ (ASE is in VNet) | +| **Private endpoints** | ❌ | ❌ | ❌ | ✅ | ✅ | +| **Always On** | ❌ | ✅ | ✅ | ✅ | ✅ | +| **Backup/Restore** | ❌ | ❌ | ✅ | ✅ | ✅ | +| **Hybrid Connections** | ❌ | ❌ | 25 | 200 | 200 | +| **Traffic Manager** | ❌ | ❌ | ✅ | ✅ | ✅ | +| **SLA** | None | None | 99.95% | 99.95% | 99.95% | + +## Pricing Overview + +| SKU | vCPU | RAM | Storage | Approx. Monthly Cost | +|-----|------|-----|---------|---------------------| +| F1 | Shared | 1 GB | 1 GB | Free | +| B1 | 1 | 1.75 GB | 10 GB | ~$55 | +| B2 | 2 | 3.5 GB | 10 GB | ~$110 | +| S1 | 1 | 1.75 GB | 50 GB | ~$73 | +| S2 | 2 | 3.5 GB | 50 GB | ~$146 | +| P1v3 | 2 | 8 GB | 250 GB | ~$138 | +| P2v3 | 4 | 16 GB | 250 GB | ~$276 | +| P3v3 | 8 | 32 GB | 250 GB | ~$552 | +| I1v2 | 2 | 8 GB | 1 TB | ~$460 | + +> 💡 **Tip:** Prices vary by region. Use the [Azure Pricing Calculator](https://azure.microsoft.com/pricing/calculator/) for exact figures. + +## Decision Criteria + +``` +Production workload? +├─ No → Free (F1) or Basic (B1) for dev/test +└─ Yes + Need deployment slots or auto-scale? + ├─ No → Basic (B1-B3) if budget-constrained + └─ Yes + Need VNet integration or private endpoints? + ├─ No → Standard (S1-S3) + └─ Yes + Need network isolation (dedicated ASE)? + ├─ Yes → Isolated (I1v2+) + └─ No + Need private endpoints? + ├─ Yes → Premium (P1v3+) + └─ No → Standard (S1+) with VNet integration +``` + +## Feature Unlock Summary + +Key features unlocked at each tier: + +| Upgrade Path | Features Gained | +|-------------|-----------------| +| Free → Basic | Custom domains, TLS/SSL, Always On | +| Basic → Standard | Deployment slots, auto-scale, VNet integration, backups | +| Standard → Premium | Private endpoints, more slots (20), higher scale (30 inst.) | +| Premium → Isolated | Full network isolation (ASE), dedicated infrastructure | + +## Bicep — App Service Plan with SKU + +```bicep +resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = { + name: planName + location: location + sku: { + name: 'P1v3' + tier: 'PremiumV3' + capacity: 2 // number of instances + } + kind: 'linux' + properties: { + reserved: true // required for Linux + } +} +``` + +## Terraform — App Service Plan with SKU + +```hcl +resource "azurerm_service_plan" "plan" { + name = var.plan_name + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + os_type = "Linux" + sku_name = "P1v3" +} +``` + +## Scaling Within a Tier + +Scale up (change SKU) vs scale out (add instances): + +| Strategy | When to Use | How | +|----------|-------------|-----| +| Scale up | App needs more CPU/RAM | Change SKU (e.g., S1 → S2) | +| Scale out | Handle more concurrent load | Increase instance count or enable auto-scale | + +> ⚠️ **Warning:** Scaling from one tier family to another (e.g., Standard to Premium) may cause a brief restart. Schedule changes during low-traffic windows. + +## Recommendations by Workload + +| Workload | Recommended SKU | Reason | +|----------|----------------|--------| +| Personal blog / prototype | F1 or B1 | Minimal cost, no SLA needed | +| Team dev/test | B1-B2 | Always On, custom domain | +| Production API | S1-S2 | Auto-scale, slots, VNet | +| Enterprise with compliance | P1v3+ | Private endpoints, 20 slots | +| Regulated / multi-tenant SaaS | I1v2+ | Full network isolation | From cd8f38b76f8bec8d512cf891b5b2cf96fa1aa2ba Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Tue, 21 Apr 2026 23:46:20 +0100 Subject: [PATCH 02/20] Update plugin/skills/azure-prepare/references/services/app-service/networking.md Updated to use up to date property which can also be audited using policy --- .../azure-prepare/references/services/app-service/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index 12ad438a2..4ea91503f 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -47,7 +47,7 @@ resource webApp 'Microsoft.Web/sites@2022-09-01' = { properties: { serverFarmId: appServicePlan.id virtualNetworkSubnetId: subnet.id - vnetRouteAllEnabled: true // route all outbound through VNet + outboundVnetRouting.allTraffic: true // route all outbound through VNet } } ``` From 5a6920acc728c3e0c72c9a2639aae99ede57cbf0 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 22 Apr 2026 21:25:10 +0100 Subject: [PATCH 03/20] Update plugin/skills/azure-prepare/references/services/app-service/networking.md standardise on using the newer outboundVnetRouting.allTraffic property Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../azure-prepare/references/services/app-service/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index 4ea91503f..b11d4f11a 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -52,7 +52,7 @@ resource webApp 'Microsoft.Web/sites@2022-09-01' = { } ``` -> 💡 **Tip:** Set `vnetRouteAllEnabled: true` to route ALL outbound traffic through the VNet. Without this, only RFC1918 traffic is routed through the VNet. +> 💡 **Tip:** Set `outboundVnetRouting.allTraffic: true` to route ALL outbound traffic through the VNet. Without this, only RFC1918 traffic is routed through the VNet. ## Private Endpoints (Inbound) From 5222654e7609918470d007b7dd898c4d9e4ca157 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 21:48:27 +0000 Subject: [PATCH 04/20] docs(azure-prepare): align App Service VNet routing property usage Agent-Logs-Url: https://github.com/microsoft/GitHub-Copilot-for-Azure/sessions/d2f63a2b-7f57-4b06-b3cd-15a79e454863 Co-authored-by: apwestgarth <1146895+apwestgarth@users.noreply.github.com> --- .../references/services/app-service/networking.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index b11d4f11a..fee5828c4 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -41,13 +41,15 @@ resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' = { } } -resource webApp 'Microsoft.Web/sites@2022-09-01' = { +resource webApp 'Microsoft.Web/sites@2024-11-01' = { name: appName location: location properties: { serverFarmId: appServicePlan.id virtualNetworkSubnetId: subnet.id - outboundVnetRouting.allTraffic: true // route all outbound through VNet + outboundVnetRouting: { + allTraffic: true // route all outbound through VNet + } } } ``` @@ -134,7 +136,7 @@ Connect to on-premises resources without VPN. Requires Standard tier or higher. | Issue | Cause | Fix | |-------|-------|-----| -| Cannot reach private DB | VNet integration not enabled | Enable VNet integration; check `vnetRouteAllEnabled` | +| Cannot reach private DB | VNet integration not enabled | Enable VNet integration; check `outboundVnetRouting.allTraffic` | | DNS resolution fails | Private DNS zone not linked | Link `privatelink.*` DNS zone to VNet | | Access restriction not working | Priority ordering wrong | Lower numbers = higher priority; check rule order | | Hybrid Connection timeout | HCM not running | Verify HCM service status on-premises | From a63a0ffe3e0fac65f1ac3a6aef0ee0898b10f37e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 19:02:19 +0000 Subject: [PATCH 05/20] docs(azure-prepare): clarify pricing basis in app service sku guide Agent-Logs-Url: https://github.com/microsoft/GitHub-Copilot-for-Azure/sessions/4e7f2946-d290-4cab-87b4-e84142b0863d Co-authored-by: apwestgarth <1146895+apwestgarth@users.noreply.github.com> --- .../references/services/app-service/sku-selection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md index 1a0464896..143c2feb0 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -30,7 +30,7 @@ | P3v3 | 8 | 32 GB | 250 GB | ~$552 | | I1v2 | 2 | 8 GB | 1 TB | ~$460 | -> 💡 **Tip:** Prices vary by region. Use the [Azure Pricing Calculator](https://azure.microsoft.com/pricing/calculator/) for exact figures. +> 💡 **Tip:** Figures are representative for **Windows OS** in **Central US**, **as of 2026-04**. Prices vary by region, OS, and offer. Use the [Azure Pricing Calculator](https://azure.microsoft.com/pricing/calculator/) for exact figures. ## Decision Criteria From dcbcc0a9d7b754cad4cec962d7575a86ccb5917a Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Mon, 27 Apr 2026 14:23:28 +0100 Subject: [PATCH 06/20] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Andrew Westgarth --- .../services/app-service/networking.md | 7 ++++--- .../services/app-service/sku-selection.md | 20 +++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index fee5828c4..0b335b358 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -10,7 +10,8 @@ VNet integration, Private Endpoints, Access Restrictions, and Hybrid Connections | Private Endpoints (inbound) | ❌ | ❌ | ✅ | ✅ | | Access Restrictions | ✅ | ✅ | ✅ | ✅ | | Hybrid Connections | ❌ | 25 | 200 | 200 | -| Service Endpoints | ❌ | ✅ | ✅ | ✅ | +| Access to service-endpoint-protected resources | ❌ | ✅ | ✅ | ✅ | +> Note: Service endpoints are configured on VNets/subnets and downstream services (e.g., Storage, SQL). App Service accesses them via VNet integration rather than enabling service endpoints directly on the app. ## VNet Integration (Outbound) @@ -96,7 +97,7 @@ resource dnsLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06- } ``` -> ⚠️ **Warning:** Private Endpoints require Premium (P1v3+) or Isolated tier. The private DNS zone `privatelink.azurewebsites.net` must be linked to the VNet for name resolution. +> ⚠️ **Warning:** Private Endpoints require Basic (B1+) or higher tier. The private DNS zone `privatelink.azurewebsites.net` must be linked to the VNet for name resolution. ## Access Restrictions @@ -128,7 +129,7 @@ siteConfig: { ## Hybrid Connections -Connect to on-premises resources without VPN. Requires Standard tier or higher. Uses Hybrid Connection Manager (HCM) agent on-premises relaying through Azure Relay. +Connect to on-premises resources without VPN. Requires Basic tier or higher. Uses Hybrid Connection Manager (HCM) agent on-premises relaying through Azure Relay. > ⚠️ **Warning:** Each Hybrid Connection maps to a single host:port endpoint. Standard tier supports 25; Premium/Isolated support 200. diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md index 143c2feb0..6e5ab2220 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -2,18 +2,18 @@ ## SKU Comparison Matrix -| Feature | Free (F1) | Basic (B1-B3) | Standard (S1-S3) | Premium (P1v3-P3v3) | Isolated (I1v2-I3v2) | +| Feature | Free (F1) | Basic (B1-B3) | Standard (S1-S3) | Premium (P0v3-P3v3 and P1Mv3-P5Mv3;P0v4-P3v4 and P1Mv4-P5Mv4) | Isolated (I1v2-I6v2) | |---------|:-:|:-:|:-:|:-:|:-:| | **Custom domains** | ❌ | ✅ | ✅ | ✅ | ✅ | | **TLS/SSL bindings** | ❌ | ✅ (SNI) | ✅ (SNI + IP) | ✅ (SNI + IP) | ✅ (SNI + IP) | | **Deployment slots** | ❌ | ❌ | 5 | 20 | 20 | | **Auto-scale** | ❌ | ❌ | ✅ (10 inst.) | ✅ (30 inst.) | ✅ (100 inst.) | -| **VNet integration** | ❌ | ❌ | ✅ | ✅ | ✅ (ASE is in VNet) | -| **Private endpoints** | ❌ | ❌ | ❌ | ✅ | ✅ | +| **VNet integration** | ❌ | ✅ | ✅ | ✅ | ✅ (ASE is in VNet) | +| **Private endpoints** | ❌ | ✅ | ✅ | ✅ | ✅ | | **Always On** | ❌ | ✅ | ✅ | ✅ | ✅ | | **Backup/Restore** | ❌ | ❌ | ✅ | ✅ | ✅ | -| **Hybrid Connections** | ❌ | ❌ | 25 | 200 | 200 | -| **Traffic Manager** | ❌ | ❌ | ✅ | ✅ | ✅ | +| **Hybrid Connections** | ❌ | 5 | 25 | 200 | 200 | +| **Traffic Manager** | ✅ | ✅ | ✅ | ✅ | ✅ | | **SLA** | None | None | 99.95% | 99.95% | 99.95% | ## Pricing Overview @@ -58,9 +58,9 @@ Key features unlocked at each tier: | Upgrade Path | Features Gained | |-------------|-----------------| -| Free → Basic | Custom domains, TLS/SSL, Always On | -| Basic → Standard | Deployment slots, auto-scale, VNet integration, backups | -| Standard → Premium | Private endpoints, more slots (20), higher scale (30 inst.) | +| Free → Basic | Custom domains, TLS/SSL, Always On, VNet Integration, Private Endpoints, Hybrid Connections (5) | +| Basic → Standard | Deployment slots, auto-scale, backups | +| Standard → Premium | More slots (20), higher scale (30 inst.) | | Premium → Isolated | Full network isolation (ASE), dedicated infrastructure | ## Bicep — App Service Plan with SKU @@ -110,6 +110,6 @@ Scale up (change SKU) vs scale out (add instances): |----------|----------------|--------| | Personal blog / prototype | F1 or B1 | Minimal cost, no SLA needed | | Team dev/test | B1-B2 | Always On, custom domain | -| Production API | S1-S2 | Auto-scale, slots, VNet | -| Enterprise with compliance | P1v3+ | Private endpoints, 20 slots | +| Production API | P0v3/P0v4-P2v3/P2v4 | Auto-scale, slots, VNet | +| Enterprise with compliance | P1v3+/P1v4+ | Private endpoints, 20 slots, 30 instances | | Regulated / multi-tenant SaaS | I1v2+ | Full network isolation | From 0dc1aedb12a8cca9bd4b9445db0b1ca4f1e4621d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:48:48 +0000 Subject: [PATCH 07/20] docs(azure-prepare): capture SSL cert thumbprint in CLI flow Agent-Logs-Url: https://github.com/microsoft/GitHub-Copilot-for-Azure/sessions/196e1c2e-01d3-48ce-b9ce-cc3fb727eb3e Co-authored-by: apwestgarth <1146895+apwestgarth@users.noreply.github.com> --- .../references/services/app-service/custom-domains.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md b/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md index eb32ec482..60be697f6 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md +++ b/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md @@ -45,6 +45,10 @@ az webapp config hostname add -n $APP -g $RG --hostname www.contoso.com # Create managed certificate (free) az webapp config ssl create -n $APP -g $RG --hostname www.contoso.com +# Capture certificate thumbprint +THUMBPRINT=$(az webapp config ssl list -n $APP -g $RG \ + --query "[?contains(hostNames, 'www.contoso.com')].thumbprint | [0]" -o tsv) + # Bind the certificate az webapp config ssl bind -n $APP -g $RG \ --certificate-thumbprint $THUMBPRINT --ssl-type SNI From 6f197972a517edab0501b2a53f444657cbf60d61 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:55:35 +0000 Subject: [PATCH 08/20] docs(azure-prepare): add Bicep TLS binding follow-up step Agent-Logs-Url: https://github.com/microsoft/GitHub-Copilot-for-Azure/sessions/892d611e-3996-426a-a266-712648f1f27c Co-authored-by: apwestgarth <1146895+apwestgarth@users.noreply.github.com> --- .../services/app-service/custom-domains.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md b/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md index 60be697f6..505824b90 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md +++ b/plugin/skills/azure-prepare/references/services/app-service/custom-domains.md @@ -78,6 +78,25 @@ resource managedCert 'Microsoft.Web/certificates@2022-09-01' = { } ``` +Then run a follow-up Bicep deployment to enable SNI and bind the managed certificate to the hostname: + +```bicep +resource managedCert 'Microsoft.Web/certificates@2022-09-01' existing = { + name: 'www.contoso.com' +} + +resource customDomainTlsBinding 'Microsoft.Web/sites/hostNameBindings@2022-09-01' = { + parent: webApp + name: 'www.contoso.com' + properties: { + siteName: webApp.name + hostNameType: 'Verified' + sslState: 'SniEnabled' + thumbprint: managedCert.properties.thumbprint + } +} +``` + > ⚠️ **Warning:** Managed certificate creation requires the DNS records to be in place first. The hostname binding must exist before requesting the certificate. ## Terraform — Custom Domain with Managed Certificate From 67551e654220e6a6bc9386af45f7c249707bd95f Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 00:00:23 +0100 Subject: [PATCH 09/20] Update networking.md Added CLI examples for VNET integration and Access Restrictions --- .../services/app-service/networking.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index 0b335b358..ed8d3220d 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -55,6 +55,17 @@ resource webApp 'Microsoft.Web/sites@2024-11-01' = { } ``` +### CLI - VNet Integration + +```bash +# Configure virtual network integration +az webapp vnet-integration add --resource-group RG --name APP --vnet VNET --subnet SUBNET + +# Update app configuration to route all outbound traffic through the virtual network integration +az resource update --resource-group RG --name APP --resource-type "Microsoft.Web/sites" --set properties.outboundVnetRouting.allTraffic=true +``` + + > 💡 **Tip:** Set `outboundVnetRouting.allTraffic: true` to route ALL outbound traffic through the VNet. Without this, only RFC1918 traffic is routed through the VNet. ## Private Endpoints (Inbound) @@ -97,6 +108,23 @@ resource dnsLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06- } ``` +### CLI - Private Endpoint + +```bash +# Retrieve web app resource id +id=$(az webapp list --resource-group RG --query '[].[id]' --output tsv) + +# Create Private Endpoint +az network private-endpoint create --connection-name CONNECTIONNAME --name private-endpoint --private-connection-resource-id $id --resource-group RG --subnet SUBNET --group-id sites --vnet-name VNET + +# Create Private DNS Zone +az network private-dns zone create --resource-group RG --name "privatelink.azurewebsites.net" + +# Link the DNS Zone to virtual network +az network private-dns link vnet create --resource-group RG --zone-name "privatelink.azurewebsites.net" --name dns-link --virtual-network VNET --registration-enabled false + +``` + > ⚠️ **Warning:** Private Endpoints require Basic (B1+) or higher tier. The private DNS zone `privatelink.azurewebsites.net` must be linked to the VNet for name resolution. ## Access Restrictions @@ -125,6 +153,19 @@ siteConfig: { } ``` +### CLI - Access Restrictions + +```bash +# Add restriction to allow traffic from set range used by the office +az webapp config access-restriction add --resource-group RG --name APP --rule-name 'allow-office' --action Allow --ip-address 203.0.113.0/24 --priority 100 + +# Add restriction to deny access from any other address range +az webapp config access-restriction add --resource-group RG --name APP --rule-name 'deny-all' --action Deny --ipAddress Any --priority 2147483647 + +# Set SCM Site (Kudu) to use same access restrictions as main site +az webapp config access-restriction set -g RG -n APP --use-same-restrictions-for-scm-site true +``` + > 💡 **Tip:** Always restrict the SCM/Kudu site too. Use `scmIpSecurityRestrictionsUseMain: true` to inherit main site rules, or define separate SCM rules. ## Hybrid Connections From 0ddea3afff516958435c70c614f25f966f4e2996 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 00:02:29 +0100 Subject: [PATCH 10/20] Apply suggestions from code review Co-authored-by: Andrew Westgarth --- .../references/services/app-service/networking.md | 14 +++++++------- .../services/app-service/sku-selection.md | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index ed8d3220d..a0c7d0247 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -4,13 +4,13 @@ VNet integration, Private Endpoints, Access Restrictions, and Hybrid Connections ## Feature Availability by SKU -| Feature | Free/Basic | Standard | Premium | Isolated | -|---------|:-:|:-:|:-:|:-:| -| VNet integration (outbound) | ❌ | ✅ | ✅ | ✅ (native) | -| Private Endpoints (inbound) | ❌ | ❌ | ✅ | ✅ | -| Access Restrictions | ✅ | ✅ | ✅ | ✅ | -| Hybrid Connections | ❌ | 25 | 200 | 200 | -| Access to service-endpoint-protected resources | ❌ | ✅ | ✅ | ✅ | +| Feature | Free | Basic | Standard | Premium | Isolated | +|---------|:-:|:-:|:-:|:-:|:-:| +| VNet integration (outbound) | ❌ | ✅ | ✅ | ✅ | ✅ (native) | +| Private Endpoints (inbound) | ❌ | ✅ | ✅ | ✅ | ✅ | +| Access Restrictions | ✅ | ✅ | ✅ | ✅ | ✅ | +| Hybrid Connections | ❌ | 5 | 25 | 200 | 200 | +| Access to service-endpoint-protected resources | ❌ | ✅ | ✅ | ✅ | ✅ | > Note: Service endpoints are configured on VNets/subnets and downstream services (e.g., Storage, SQL). App Service accesses them via VNet integration rather than enabling service endpoints directly on the app. ## VNet Integration (Outbound) diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md index 6e5ab2220..3b39988a1 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -66,7 +66,7 @@ Key features unlocked at each tier: ## Bicep — App Service Plan with SKU ```bicep -resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = { +resource appServicePlan 'Microsoft.Web/serverfarms@2025-03-01' = { name: planName location: location sku: { From f837c785d7a50b41b7d672bb23e5aed54846f388 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 00:20:40 +0100 Subject: [PATCH 11/20] Update plugin/skills/azure-prepare/references/services/app-service/networking.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../azure-prepare/references/services/app-service/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index a0c7d0247..655231dd5 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -112,7 +112,7 @@ resource dnsLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06- ```bash # Retrieve web app resource id -id=$(az webapp list --resource-group RG --query '[].[id]' --output tsv) +id=$(az webapp show --name APP --resource-group RG --query id --output tsv) # Create Private Endpoint az network private-endpoint create --connection-name CONNECTIONNAME --name private-endpoint --private-connection-resource-id $id --resource-group RG --subnet SUBNET --group-id sites --vnet-name VNET From 92bf0a27d65f7bd2f8d7292efc526ea562e93e36 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 17:19:56 +0100 Subject: [PATCH 12/20] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../azure-prepare/references/services/app-service/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index 655231dd5..0e70502dd 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -160,7 +160,7 @@ siteConfig: { az webapp config access-restriction add --resource-group RG --name APP --rule-name 'allow-office' --action Allow --ip-address 203.0.113.0/24 --priority 100 # Add restriction to deny access from any other address range -az webapp config access-restriction add --resource-group RG --name APP --rule-name 'deny-all' --action Deny --ipAddress Any --priority 2147483647 +az webapp config access-restriction add --resource-group RG --name APP --rule-name 'deny-all' --action Deny --ip-address Any --priority 2147483647 # Set SCM Site (Kudu) to use same access restrictions as main site az webapp config access-restriction set -g RG -n APP --use-same-restrictions-for-scm-site true From ae870a4386fd6d4e8dcbbfd657592ecc49700792 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 17:23:47 +0100 Subject: [PATCH 13/20] Updated decision tree --- .../references/services/app-service/sku-selection.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md index 3b39988a1..7e9f2a1a8 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -36,18 +36,16 @@ ``` Production workload? +Production workload? ├─ No → Free (F1) or Basic (B1) for dev/test └─ Yes - Need deployment slots or auto-scale? + Need deployment slots, auto-scale, VNET integration or Private Endpoints? ├─ No → Basic (B1-B3) if budget-constrained └─ Yes - Need VNet integration or private endpoints? - ├─ No → Standard (S1-S3) - └─ Yes Need network isolation (dedicated ASE)? ├─ Yes → Isolated (I1v2+) └─ No - Need private endpoints? + Need more deployment slots (20), instances (30)? ├─ Yes → Premium (P1v3+) └─ No → Standard (S1+) with VNet integration ``` From eff24b6f359d8d84bbf6bcceb6ed2195efb3b4ac Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 17:26:23 +0100 Subject: [PATCH 14/20] Update skill references for App Service --- .../azure-prepare/references/services/app-service/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugin/skills/azure-prepare/references/services/app-service/README.md b/plugin/skills/azure-prepare/references/services/app-service/README.md index 07c7f0a04..1e76199c9 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/README.md +++ b/plugin/skills/azure-prepare/references/services/app-service/README.md @@ -63,3 +63,6 @@ Endpoint should return 200 OK when healthy. - [Bicep Patterns](bicep.md) - [Deployment Slots](deployment-slots.md) - [Auto-Scaling](scaling.md) +- [Networking](networking.md) +- [SKU Selection](sku-selection.md) +- [Custom Domains](custom-domains.md) From 1c007dbdf31e82640800410d3b7064829995c9e3 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 17:27:35 +0100 Subject: [PATCH 15/20] Added mention of Hybrid Connections support at Basic tier level --- .../azure-prepare/references/services/app-service/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index 0e70502dd..3f1e061bb 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -172,7 +172,7 @@ az webapp config access-restriction set -g RG -n APP --use-same-restrictions-for Connect to on-premises resources without VPN. Requires Basic tier or higher. Uses Hybrid Connection Manager (HCM) agent on-premises relaying through Azure Relay. -> ⚠️ **Warning:** Each Hybrid Connection maps to a single host:port endpoint. Standard tier supports 25; Premium/Isolated support 200. +> ⚠️ **Warning:** Each Hybrid Connection maps to a single host:port endpoint. Basic tier suports 5; Standard tier supports 25; Premium/Isolated support 200. ## Troubleshooting From 14b7464aaf03f767b7778ed45120d81ee5489935 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 17:29:08 +0100 Subject: [PATCH 16/20] Fixed duplication of title in Decision tree --- .../references/services/app-service/sku-selection.md | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md index 7e9f2a1a8..f46df27a5 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -36,7 +36,6 @@ ``` Production workload? -Production workload? ├─ No → Free (F1) or Basic (B1) for dev/test └─ Yes Need deployment slots, auto-scale, VNET integration or Private Endpoints? From 47eaed1da45c2e3f22868c1ceeef3627cd32cf1e Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 17:29:10 +0100 Subject: [PATCH 17/20] Fixed duplication of title in Decision tree From 9999dda67a9cdc1f330594d27a93042687419171 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 18:16:39 +0100 Subject: [PATCH 18/20] Update plugin/skills/azure-prepare/references/services/app-service/networking.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../references/services/app-service/networking.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index 3f1e061bb..6994cfcca 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -106,6 +106,21 @@ resource dnsLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06- registrationEnabled: false } } + +resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-11-01' = { + parent: privateEndpoint + name: 'default' + properties: { + privateDnsZoneConfigs: [ + { + name: 'webapp-dns-zone' + properties: { + privateDnsZoneId: privateDnsZone.id + } + } + ] + } +} ``` ### CLI - Private Endpoint From c1d32e53f9dcd3cdd3fb7e268006752cbe167b32 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 17:19:43 +0000 Subject: [PATCH 19/20] docs(azure-prepare): align app service decision guidance with SKU matrix Agent-Logs-Url: https://github.com/microsoft/GitHub-Copilot-for-Azure/sessions/9ace98f0-e9ee-45a0-8fab-dd39082db62d Co-authored-by: apwestgarth <1146895+apwestgarth@users.noreply.github.com> --- .../services/app-service/networking.md | 2 +- .../services/app-service/sku-selection.md | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugin/skills/azure-prepare/references/services/app-service/networking.md b/plugin/skills/azure-prepare/references/services/app-service/networking.md index 6994cfcca..d3b5e9543 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/networking.md +++ b/plugin/skills/azure-prepare/references/services/app-service/networking.md @@ -187,7 +187,7 @@ az webapp config access-restriction set -g RG -n APP --use-same-restrictions-for Connect to on-premises resources without VPN. Requires Basic tier or higher. Uses Hybrid Connection Manager (HCM) agent on-premises relaying through Azure Relay. -> ⚠️ **Warning:** Each Hybrid Connection maps to a single host:port endpoint. Basic tier suports 5; Standard tier supports 25; Premium/Isolated support 200. +> ⚠️ **Warning:** Each Hybrid Connection maps to a single host:port endpoint. Basic tier supports 5; Standard tier supports 25; Premium/Isolated support 200. ## Troubleshooting diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md index f46df27a5..7fdfa4788 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -38,15 +38,15 @@ Production workload? ├─ No → Free (F1) or Basic (B1) for dev/test └─ Yes - Need deployment slots, auto-scale, VNET integration or Private Endpoints? - ├─ No → Basic (B1-B3) if budget-constrained + Need deployment slots, auto-scale, or backups? + ├─ No → Basic (B1-B3) if budget-constrained (supports VNet integration and Private Endpoints) └─ Yes - Need network isolation (dedicated ASE)? - ├─ Yes → Isolated (I1v2+) - └─ No - Need more deployment slots (20), instances (30)? - ├─ Yes → Premium (P1v3+) - └─ No → Standard (S1+) with VNet integration + Need network isolation (dedicated ASE)? + ├─ Yes → Isolated (I1v2+) + └─ No + Need more than 5 deployment slots or more than 10 instances? + ├─ Yes → Premium (P1v3+) + └─ No → Standard (S1-S3) with Private Endpoints and VNet integration ``` ## Feature Unlock Summary @@ -107,6 +107,6 @@ Scale up (change SKU) vs scale out (add instances): |----------|----------------|--------| | Personal blog / prototype | F1 or B1 | Minimal cost, no SLA needed | | Team dev/test | B1-B2 | Always On, custom domain | -| Production API | P0v3/P0v4-P2v3/P2v4 | Auto-scale, slots, VNet | +| Production API | S1-S3 (P0v3/P0v4+ for higher scale/perf) | Auto-scale, slots, VNet | | Enterprise with compliance | P1v3+/P1v4+ | Private endpoints, 20 slots, 30 instances | | Regulated / multi-tenant SaaS | I1v2+ | Full network isolation | From b0dced3f71a91994c606cef2c707177bf40a1d78 Mon Sep 17 00:00:00 2001 From: Andrew Westgarth Date: Wed, 29 Apr 2026 18:36:02 +0100 Subject: [PATCH 20/20] Apply suggestion from @apwestgarth Added detail on reserved instances and savings plans --- .../references/services/app-service/sku-selection.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md index 7fdfa4788..681ff1d92 100644 --- a/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md +++ b/plugin/skills/azure-prepare/references/services/app-service/sku-selection.md @@ -32,6 +32,12 @@ > 💡 **Tip:** Figures are representative for **Windows OS** in **Central US**, **as of 2026-04**. Prices vary by region, OS, and offer. Use the [Azure Pricing Calculator](https://azure.microsoft.com/pricing/calculator/) for exact figures. +### Save by using Reserved Instances and Savings Plans + +Cost savings can be made on Premium V3, Premium V4 and Isolated V2 plans by committing to reserved instances for 1 or 3 year terms, details can found at [https://learn.microsoft.com/azure/cost-management-billing/reservations/prepay-app-service](https://learn.microsoft.com/azure/cost-management-billing/reservations/prepay-app-service). + +Alternatively cost savings can be made using [Azure Savings plans](https://learn.microsoft.com/en-us/azure/cost-management-billing/savings-plan/). + ## Decision Criteria ```