--- id: JosiahSiegel/claude-plugin-marketplace/deployment-stacks-2025 version: "716c9530" license: MIT install: manual updated: 2026-06-18 --- # deployment-stacks-2025 — This skill covers Azure Deployment Stacks, the GA successor to Azure Blueprints, enabling you to manage collections of Azure resources as atomic units with unified lifecycle control. Learn to configure deny settings for resource protection, set cleanup policies via ActionOnUnmanage, and deploy stacks across resource group, subscription, and management group scopes. Includes Bicep templates, az CLI commands, and migration guidance from Blueprints. Publisher: JosiahSiegel · Stars: 49 · Updated: 2026-06-18 Install (manual): `git clone https://github.com/JosiahSiegel/claude-plugin-marketplace` ## SKILL.md # Azure Deployment Stacks - 2025 GA Features Complete knowledge base for Azure Deployment Stacks, the successor to Azure Blueprints (GA 2024, best practices 2025). ## Overview Azure Deployment Stacks is a resource type for managing a collection of Azure resources as a single, atomic unit. It provides unified lifecycle management, resource protection, and automatic cleanup capabilities. ## Key Features ### 1. Unified Resource Management - Manage multiple resources as a single entity - Update, export, and delete operations on the entire stack - Track all managed resources in one place - Consistent deployment across environments ### 2. Deny Settings (Resource Protection) Prevent unauthorized modifications to managed resources: - **None**: No restrictions (default) - **DenyDelete**: Prevent resource deletion - **DenyWriteAndDelete**: Prevent updates and deletions ### 3. ActionOnUnmanage (Cleanup Policies) Control what happens to resources no longer in template: - **detachAll**: Remove from stack management, keep resources - **deleteAll**: Delete resources not in template - **deleteResources**: Delete unmanaged resources, keep resource groups ### 4. Scope Flexibility Deploy stacks at: - Resource group scope - Subscription scope - Management group scope ### 5. Replaces Azure Blueprints Azure Blueprints will be deprecated in **July 2026**. Deployment Stacks is the recommended replacement. ## Prerequisites ### Azure CLI Version ```bash # Requires Azure CLI 2.61.0 or later az version # Upgrade if needed az upgrade ``` ### Azure PowerShell Version ```bash # Requires Azure PowerShell 12.0.0 or later Get-InstalledModule -Name Az Update-Module -Name Az ``` ## Creating Deployment Stacks ### Subscription Scope Stack ```bash # Create deployment stack at subscription level az stack sub create \ --name MyProductionStack \ --location eastus \ --template-file main.bicep \ --parameters @parameters.json \ --deny-settings-mode DenyWriteAndDelete \ --deny-settings-excluded-principals \ --action-on-unmanage deleteAll \ --description "Production infrastructure managed by deployment stack" \ --tags Environment=Production ManagedBy=DeploymentStack CostCenter=Engineering # What-if analysis before deployment az stack sub what-if \ --name MyProductionStack \ --location eastus \ --template-file main.bicep \ --parameters @parameters.json # Create with confirmation prompt disabled az stack sub create \ --name MyDevStack \ --location eastus \ --template-file main.bicep \ --deny-settings-mode None \ --action-on-unmanage detachAll \ --yes ``` ### Resource Group Scope Stack ```bash # Create resource group az group create \ --name MyRG \ --location eastus \ --tags Environment=Production # Create deployment stack az stack group create \ --name MyAppStack \ --resource-group MyRG \ --template-file main.bicep \ --parameters environment=production \ --deny-settings-mode DenyDelete \ --action-on-unmanage deleteAll \ --description "Application infrastructure stack" ``` ### Management Group Scope Stack ```bash # Create stack at management group level az stack mg create \ --name MyEnterpriseStack \ --management-group-id MyMgmtGroup \ --location eastus \ --template-file main.bicep \ --deny-settings-mode DenyWriteAndDelete \ --action-on-unmanage detachAll ``` ## Bicep Template for Deployment Stack ### Production Stack Template ```bicep // main.bicep targetScope = 'subscription' @description('Environment name') @allowed([ 'dev' 'staging' 'production' ]) param environment string = 'production' @description('Primary location') param location string = 'eastus' @description('Secondary location for geo-replication') param secondaryLocation string = 'westus' // Resource naming var namingPrefix = 'myapp-${environment}' // Resource Group for core infrastructure resource coreRG 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: '${namingPrefix}-core-rg' location: location tags: { Environment: environment ManagedBy: 'DeploymentStack' Purpose: 'Core Infrastructure' } } // Resource Group for data services resource dataRG 'Microsoft.Resources/resourceGroups@2024-03-01' = { name: '${namingPrefix}-data-rg' location: location tags: { Environment: environment ManagedBy: 'DeploymentStack' Purpose: 'Data Services' } } // Log Analytics Workspace module logAnalytics 'modules/log-analytics.bicep' = { name: 'logAnalyticsDeploy' scope: coreRG params: { name: '${namingPrefix}-logs' location: location retentionInDays: environment == 'production' ? 90 : 30 } } // AKS Automatic Cluster module aksCluster 'modules/aks-automatic.bicep' = { name: 'aksClusterDeploy' scope: coreRG params: { name: '${namingPrefix}-aks' location: location kubernetesVersion: '1.34' workspaceId: logAnalytics.outputs.workspaceId enableZoneRedundancy: environment == 'production' } } // Container Apps Environment module containerEnv 'modules/container-env.bicep' = { name: 'containerEnvDeploy' scope: coreRG params: { name: '${namingPrefix}-containerenv' location: location workspaceId: logAnalytics.outputs.workspaceId zoneRedundant: environment == 'production' } } // Azure OpenAI module openAI 'modules/openai.bicep' = { name: 'openAIDeploy' scope: dataRG params: { name: '${namingPrefix}-openai' location: location deployGPT5: environment == 'production' } } // Cosmos DB with geo-replication module cosmosDB 'modules/cosmos-db.bicep' = { name: 'cosmosDBDeploy' scope: dataRG params: { name: '${namingPrefix}-cosmos' primaryLocation: location secondaryLocation: secondaryLocation enableAutomaticFailover: environment == 'production' } } // Key Vault module keyVault 'modules/key-vault.bicep' = { name: 'keyVaultDeploy' scope: coreRG params: { name: '${namingPrefix}-kv' location: location enablePurgeProtection: environment == 'production' } } // Outputs output aksClusterName string = aksCluster.outputs.clusterName output containerEnvId string = containerEnv.outputs.environmentId output openAIEndpoint string = openAI.outputs.endpoint output cosmosDBEndpoint string = cosmosDB.outputs.endpoint output keyVaultUri string = keyVault.outputs.vaultUri ``` ### AKS Automatic Module ```bicep // modules/aks-automatic.bicep @description('Cluster name') param name string @description('Location') param location string @description('Kubernetes version') param kubernetesVersion string = '1.34' @description('Log Analytics workspace ID') param workspaceId string @description('Enable zone redundancy') param enableZoneRedundancy bool = true resource aksCluster 'Microsoft.ContainerService/managedClusters@2025-01-01' = { name: name location: location sku: { name: 'Automatic' tier: 'Standard' } identity: { type: 'SystemAssigned' } properties: { kubernetesVersion: kubernetesVersion dnsPrefix: '${name}-dns' enableRBAC: true aadProfile: { managed: true enableAzureRBAC: true } networkProfile: { networkPlugin: 'azure' networkPluginMode: 'overlay' networkDataplane: 'cilium' serviceCidr: '10.0.0.0/16' dnsServiceIP: '10.0.0.10' } autoScalerProfile: { 'balance-similar-node-groups': 'true' expander: 'least-waste' } autoUpgradeProfile: { upgradeChannel: 'stable' nodeOSUpgradeChannel: 'NodeImage' } securityProfile: { defender: { securityMonitoring: { enabled: true } } workloadIdentity: { enabled: true } } oidcIssuerProfile: { enabled: true } addonProfiles: { omsagent: { enabled: true config: { logAnalyticsWorkspaceResourceID: workspaceId } } azurePolicy: { enabled: true } } } zones: enableZoneRedundancy ? ['1', '2', '3'] : null } output clusterName string = aksCluster.name output clusterId string = aksCluster.id output oidcIssuerUrl string = aksCluster.properties.oidcIssuerProfile.issuerUrl output kubeletIdentity string = aksCluster.properties.identityProfile.kubeletidentity.objectId ``` ## Managing Deployment Stacks ### Update Stack ```bash # Update with new template version az stack sub update \ --name MyProductionStack \ --template-file main.bicep \ --parameters @parameters.json \ --action-on-unmanage deleteAll # Update deny settings az stack sub update \ --name MyProductionStack \ --deny-settings-mode DenyWriteAndDelete \ --deny-settings-excluded-principals ``` ### View Stack Details ```bash # Show stack information az stack sub show \ --name MyProductionStack \ --output json # List all stacks in subscription az stack sub list --output table # List stacks in resource group az stack group list \ --resource-group MyRG \ --output table ``` ### Export Stack Template ```bash # Export template from deployed stack az stack sub export \ --name MyProductionStack \ --output-file exported-stack.json # Export and save parameters az stack sub show \ --name MyProductionStack \ --query "parameters" \ --output json > parameters-backup.json ``` ### Delete Stack ```bash # Delete stack and all managed resources az stack sub delete \ --name MyProductionStack \ --action-on-unmanage deleteAll \ --yes # Delete stack but keep resources az stack sub delete \ --name MyProductionStack \ --action-on-unmanage detachAll \ --yes # Delete with confirmation prompt az stack sub delete --name MyProductionStack ``` ## Deny Settings in Detail ### DenyDelete Mode Prevents deletion but allows updates: ```bash az stack sub create \ --name MyStack \ --location eastus \ --template-file main.bicep \ --deny-settings-mode DenyDelete \ --deny-settings-excluded-principals \ \ ``` **Use cases:** - Protect production databases - Prevent accidental resource deletion - Allow configuration updates ### DenyWriteAndDelete Mode Prevents both updates and deletions: ```bash az stack sub create \ --name MyStack \ --location eastus \ --template-file main.bicep \ --deny-settings-mode DenyWriteAndDelete \ --deny-settings-excluded-principals ``` **Use cases:** - Immutable infrastructure - Compliance requirements - Critical production workloads ### Excluded Principals Bypass deny settings for specific identities: ```bash # Get principal IDs SERVICE_PRINCIPAL_ID=$(az ad sp show --id --query id -o tsv) ADMIN_GROUP_ID=$(az ad group show --group "Cloud Admins" --query id -o tsv) # Apply with exclusions az stack sub create \ --name MyStack \ --location eastus \ --template-file main.bicep \ --deny-settings-mode DenyWriteAndDelete \ --deny-settings-excluded-principals $SERVICE_PRINCIPAL_ID $ADMIN_GROUP_ID ``` ## ActionOnUnmanage Policies ### detachAll Resources are removed from stack management but not deleted: ```bash az stack sub create \ --name MyStack \ --location eastus \ --template-file main.bicep \ --action-on-unmanage detachAll ``` **Use when:** - Testing deployment changes - Migrating resources to another stack - Temporary stack management ### deleteAll All unmanaged resources are deleted: ```bash az stack sub create \ --name MyStack \ --location eastus \ --template-file main.bicep \ --action-on-unmanage deleteAll ``` **Use when:** - Ephemeral environments (dev, test) - Clean slate deployments - Strict infrastructure-as-code enforcement ### deleteResources Delete resources but keep resource groups: ```bash az stack sub create \ --name MyStack \ --location eastus \ --template-file main.bicep \ --action-on-unmanage deleteResources ``` ## RBAC for Deployment Stacks ### Built-in Roles **Azure Deployment Stack Contributor** - Manage deployment stacks - Cannot create or delete deny-assignments **Azure Deployment Stack Owner** - Full stack management - Can create and delete deny-assignments ### Assign Roles ```bash # Assign Stack Contributor role az role assignment create \ --assignee \ --role "Azure Deployment Stack Contributor" \ --scope /subscriptions/ # Assign Stack Owner role az role assignment create \ --assignee \ --role "Azure Deployment Stack Owner" \ --scope /subscriptions/ ``` ## CI/CD, Monitoring and Auditing Detailed GitHub Actions and Azure DevOps CI/CD examples for deployment stacks, plus monitoring, audit queries, deployment history checks, and operational observability live in `references/cicd-monitoring.md`. Load that reference when productionizing stack deployments or auditing changes. ## Migration from Azure Blueprints ### Assessment 1. **Inventory Blueprints**: List all blueprints and assignments 2. **Document Parameters**: Export parameters and configurations 3. **Plan Conversion**: Map blueprints to deployment stacks 4. **Test in Dev**: Validate converted templates ### Conversion Steps ```bash # 1. Export Blueprint as ARM template # (Use Azure Portal or PowerShell) # 2. Convert ARM to Bicep az bicep decompile --file blueprint-template.json # 3. Create Deployment Stack az stack sub create \ --name ConvertedFromBlueprint \ --location eastus \ --template-file converted.bicep \ --parameters @blueprint-parameters.json \ --deny-settings-mode DenyWriteAndDelete \ --action-on-unmanage detachAll # 4. Validate resources az stack sub show --name ConvertedFromBlueprint # 5. Delete Blueprint assignment (after validation) # Remove-AzBlueprintAssignment -Name MyBlueprintAssignment ``` ## Best Practices ✓ **Use Deployment Stacks for all new infrastructure** ✓ **Always run what-if analysis before deployment** ✓ **Use DenyWriteAndDelete for production stacks** ✓ **Exclude break-glass principals from deny settings** ✓ **Tag stacks with Environment, CostCenter, Owner** ✓ **Use deleteAll for ephemeral environments** ✓ **Use detachAll for migration scenarios** ✓ **Implement CI/CD pipelines for stack deployment** ✓ **Monitor stack operations via activity logs** ✓ **Document stack architecture and dependencies** ## Troubleshooting ### Stack Creation Fails ```bash # Check deployment errors az stack sub show \ --name MyStack \ --query "error" \ --output json # Validate template az deployment sub validate \ --location eastus \ --template-file main.bicep \ --parameters @parameters.json ``` ### Deny Settings Blocking Operations ```bash # Check deny assignments az role assignment list \ --scope /subscriptions/ \ --include-inherited \ --query "[?type=='Microsoft.Authorization/denyAssignments']" # Add principal to exclusions az stack sub update \ --name MyStack \ --deny-settings-excluded-principals ``` ### Resources Not Deleted ```bash # Check action-on-unmanage setting az stack sub show \ --name MyStack \ --query "actionOnUnmanage" \ --output tsv # Update to deleteAll az stack sub update \ --name MyStack \ --action-on-unmanage deleteAll ``` ## References - [Deployment Stacks Documentation](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/deployment-stacks) - [Deployment Stacks Quickstart](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/quickstart-create-deployment-stacks) - [Migrate from Blueprints](https://learn.microsoft.com/en-us/azure/governance/blueprints/how-to/migrate-to-deployment-stacks) Deployment Stacks represents the future of Azure infrastructure lifecycle management! [View on SkillFed](https://skillfed.io/JosiahSiegel/claude-plugin-marketplace/deployment-stacks-2025) · [View on GitHub](https://github.com/JosiahSiegel/claude-plugin-marketplace)