Resource group deployments with Bicep files

This article describes how to set scope with Bicep when deploying to a resource group.

Supported resources

Most resources can be deployed to a resource group. For a list of available resources, see ARM template reference.

Set scope

By default, a Bicep file is scoped to the resource group. If you want to explicitly set the scope, use:

targetScope = 'resourceGroup'

But, setting the target scope to resource group is unnecessary because that scope is used by default.

Deployment commands

To deploy to a resource group, use the resource group deployment commands.

For Azure CLI, use az deployment group create. The following example deploys a template to create a resource group. The resource group you specify in the --resource-group parameter is the target resource group.

az deployment group create \
  --name demoRGDeployment \
  --resource-group ExampleGroup \
  --template-file main.bicep \
  --parameters storageAccountType=Standard_GRS

For more detailed information about deployment commands and options for deploying ARM templates, see:

Deployment scopes

When deploying to a resource group, you can deploy resources to:

  • the target resource group for the deployment operation
  • other resource groups in the same subscription or other subscriptions
  • any subscription in the tenant
  • the tenant for the resource group

An extension resource can be scoped to a target that is different than the deployment target.

The user deploying the template must have access to the specified scope.

This section shows how to specify different scopes. You can combine these different scopes in a single template.

Scope to target resource group

To deploy resources to the target resource group, add those resources to the Bicep file.

// resource deployed to target resource group
resource exampleResource 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  ...
}

For an example template, see Deploy to target resource group.

Scope to different resource group

To deploy resources to a resource group that isn't the target resource group, add a module. Use the resourceGroup function to set the scope property for that module.

If the resource group is in a different subscription, provide the subscription ID and the name of the resource group. If the resource group is in the same subscription as the current deployment, provide only the name of the resource group. If you don't specify a subscription in the resourceGroup function, the current subscription is used.

The following example shows a module that targets a resource group in a different subscription.

param otherResourceGroup string
param otherSubscriptionID string

// module deployed to different subscription and resource group
module exampleModule 'module.bicep' = {
  name: 'otherSubAndRG'
  scope: resourceGroup(otherSubscriptionID, otherResourceGroup)
}

The next example shows a module that targets a resource group in the same subscription.

param otherResourceGroup string

// module deployed to resource group in the same subscription
module exampleModule 'module.bicep' = {
  name: 'otherRG'
  scope: resourceGroup(otherResourceGroup)
}

For an example template, see Deploy to multiple resource groups.

Scope to subscription

To deploy resources to a subscription, add a module. Use the subscription function to set its scope property.

To deploy to the current subscription, use the subscription function without a parameter.


// module deployed at subscription level
module exampleModule 'module.bicep' = {
  name: 'deployToSub'
  scope: subscription()
}

To deploy to a different subscription, specify that subscription ID as a parameter in the subscription function.

param otherSubscriptionID string

// module deployed at subscription level but in a different subscription
module exampleModule 'module.bicep' = {
  name: 'deployToSub'
  scope: subscription(otherSubscriptionID)
}

For an example template, see Create resource group with Bicep.

Scope to tenant

To create resources at the tenant, add a module. Use the tenant function to set its scope property.

The user deploying the template must have the required access to deploy at the tenant.

The following example includes a module that is deployed to the tenant.

// module deployed at tenant level
module exampleModule 'module.bicep' = {
  name: 'deployToTenant'
  scope: tenant()
}

Instead of using a module, you can set the scope to tenant() for some resource types. The following example deploys a management group at the tenant.

param mgName string = 'mg-${uniqueString(newGuid())}'

// ManagementGroup deployed at tenant
resource managementGroup 'Microsoft.Management/managementGroups@2023-04-01' = {
  scope: tenant()
  name: mgName
  properties: {}
}

output output string = mgName

For more information, see Management group.

Deploy to target resource group

To deploy resources in the target resource group, define those resources in the resources section of the template. The following template creates a storage account in the resource group that is specified in the deployment operation.

@minLength(3)
@maxLength(11)
param storagePrefix string

@allowed([
  'Standard_LRS'
  'Standard_GRS'
  'Standard_RAGRS'
  'Standard_ZRS'
  'Premium_LRS'
  'Premium_ZRS'
  'Standard_GZRS'
  'Standard_RAGZRS'
])
param storageSKU string = 'Standard_LRS'

param location string = resourceGroup().location

var uniqueStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}'

resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: uniqueStorageName
  location: location
  sku: {
    name: storageSKU
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
  }
}

output storageEndpoint object = stg.properties.primaryEndpoints

Deploy to multiple resource groups

You can deploy to more than one resource group in a single Bicep file.

Note

You can deploy to 800 resource groups in a single deployment. Typically, this limitation means you can deploy to one resource group specified for the parent template, and up to 799 resource groups in nested or linked deployments. However, if your parent template contains only nested or linked templates and does not itself deploy any resources, then you can include up to 800 resource groups in nested or linked deployments.

The following example deploys two storage accounts. The first storage account is deployed to the resource group specified in the deployment operation. The second storage account is deployed to the resource group specified in the secondResourceGroup and secondSubscriptionID parameters:

@maxLength(11)
param storagePrefix string

param firstStorageLocation string = resourceGroup().location

param secondResourceGroup string
param secondSubscriptionID string = ''
param secondStorageLocation string

var firstStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}'
var secondStorageName = '${storagePrefix}${uniqueString(secondSubscriptionID, secondResourceGroup)}'

module firstStorageAcct 'storage.bicep' = {
  name: 'storageModule1'
  params: {
    storageLocation: firstStorageLocation
    storageName: firstStorageName
  }
}

module secondStorageAcct 'storage.bicep' = {
  name: 'storageModule2'
  scope: resourceGroup(secondSubscriptionID, secondResourceGroup)
  params: {
    storageLocation: secondStorageLocation
    storageName: secondStorageName
  }
}

Both modules use the same Bicep file named storage.bicep.

param storageLocation string
param storageName string

resource storageAcct 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: storageName
  location: storageLocation
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'Storage'
  properties: {}
}

Create resource group

For information about creating resource groups, see Create resource group with Bicep.

Next steps

To learn about other scopes, see: