This quickstart shows you how to package an Azure Resource Manager template (ARM template) into a template spec. Then, you deploy that template spec. Your template spec contains an ARM template that deploys a storage account.
Prerequisites
An Azure account with an active subscription. Create an account for free.
Create template
You create a template spec from an ARM template. Copy the following template and save as C:\Templates\createStorageV1.json.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string",
"defaultValue": "[uniqueString(resourceGroup().id)]"
},
"___location": {
"type": "string",
"defaultValue": "[resourceGroup().___location]"
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-01-01",
"name": "[parameters('storageAccountName')]",
"___location": "[parameters('___location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"accessTier": "Hot"
}
}
]
}
Create template spec
The template spec is a resource type named Microsoft.Resources/templateSpecs
. To create a template spec, use PowerShell, Azure CLI, the portal, or an ARM template.
Create a new resource group to contain the template spec.
New-AzResourceGroup `
-Name templateSpecRG `
-Location westus2
Create the template spec in that resource group. Give the new template spec the name storageSpec.
New-AzTemplateSpec `
-Name storageSpec `
-Version "1.0" `
-ResourceGroupName templateSpecRG `
-Location westus2 `
-TemplateFile "C:\Templates\createStorageV1.json"
Create a new resource group to contain the template spec.
az group create \
--name templateSpecRG \
--___location westus2
Create the template spec in that resource group. Give the new template spec the name storageSpec.
az ts create \
--name storageSpec \
--version "1.0" \
--resource-group templateSpecRG \
--___location "westus2" \
--template-file "C:\Templates\createStorageV1.json"
Sign in to the Azure portal.
Search for template specs. Select Template specs from the available options.
Select Import template, and then follow the instructions to import C:\Templates\createStorageV1.json that you saved earlier.
Provide the following values:
- Name: enter a name for the template spec. For example, storageSpec.
- Subscription: select an Azure subscription used for creating the template spec.
- Resource Group: select Create new, and then enter a new resource group name. For example, templateSpecRG.
- Location: select a ___location for the resource group. For example, West US 2.
- Version: enter a version for the template spec. Use 1.0.
Select Review + Create, and then select Create.
Note
We recommend using PowerShell or CLI instead of an ARM template to create your template spec. These tools automatically convert linked templates into artifacts associated with the main template. If you use an ARM template, you'll need to manually add linked templates as artifacts, which can be more complex.
When you use an ARM template to create the template spec, the template is embedded in the resource definition. Copy the following template and save it locally as createTemplateSpec.json.
Note
In the embedded template, all template expressions must be escaped with a second left bracket. Use "[[
instead of "[
. JSON arrays still use a single left bracket. See the name and ___location properties in the example below.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Resources/templateSpecs",
"apiVersion": "2022-02-01",
"name": "storageSpec",
"___location": "westus2",
"properties": {
"displayName": "Storage template spec"
}
},
{
"type": "Microsoft.Resources/templateSpecs/versions",
"apiVersion": "2022-02-01",
"name": "[format('{0}/{1}', 'storageSpec', '1.0')]",
"___location": "westus2",
"properties": {
"mainTemplate": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string",
"defaultValue": "[uniqueString(resourceGroup().id)]"
},
"___location": {
"type": "string",
"defaultValue": "[resourceGroup().___location]"
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-01-01",
"name": "[[parameters('storageAccountName')]",
"___location": "[[parameters('___location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"accessTier": "Hot"
}
}
]
}
},
"dependsOn": [
"storageSpec"
]
}
]
}
Use Azure CLI or PowerShell to create a new resource group.
New-AzResourceGroup `
-Name templateSpecRG `
-Location westus2
az group create \
--name templateSpecRG \
--___location westus2
Deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName templateSpecRG `
-TemplateFile "C:\Templates\createTemplateSpec.json"
az deployment group create \
--resource-group templateSpecRG \
--template-file "C:\Templates\createTemplateSepc.json"
Verify the deployment with Azure CLI or PowerShell.
Get-AzTemplateSpec `
-ResourceGroupName templateSpecRG `
-Name storageSpec
az ts show \
--resource-group templateSpecRG \
--name storageSpec
Deploy template spec
To deploy a template spec, use the same deployment commands as you would use to deploy a template. Pass in the resource ID of the template spec to deploy.
Create a resource group to contain the new storage account.
New-AzResourceGroup `
-Name storageRG `
-Location westus2
Get the resource ID of the template spec.
$id = (Get-AzTemplateSpec -ResourceGroupName templateSpecRG -Name storageSpec -Version "1.0").Versions.Id
Deploy the template spec.
New-AzResourceGroupDeployment `
-TemplateSpecId $id `
-ResourceGroupName storageRG
Provide parameters exactly as you would for an ARM template. Redeploy the template spec with a parameter for the storage account type.
New-AzResourceGroupDeployment `
-TemplateSpecId $id `
-ResourceGroupName storageRG `
-storageAccountType Standard_GRS
Create a resource group to contain the new storage account.
az group create \
--name storageRG \
--___location westus2
Get the resource ID of the template spec.
id=$(az ts show --name storageSpec --resource-group templateSpecRG --version "1.0" --query "id")
Note
There's a known issue with getting a template spec ID and assigning it to a variable in Windows PowerShell.
Deploy the template spec.
az deployment group create \
--resource-group storageRG \
--template-spec $id
Provide parameters exactly as you would for an ARM template. Redeploy the template spec with a parameter for the storage account type.
az deployment group create \
--resource-group storageRG \
--template-spec $id \
--parameters storageAccountType='Standard_GRS'
Select the template spec you created. Use the search box to find the template spec if there are many.
Select Deploy.
Provide the following values:
- Subscription: select an Azure subscription for creating the resource.
- Resource group: select Create new and then enter storageRG.
Select Review + create, and then select Create.
Copy the following template and save it locally to a file named C:\Templates\deployTemplateSpecV1.json.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2025-04-01",
"name": "demo",
"properties": {
"templateLink": {
"id": "[resourceId('templateSpecRG', 'Microsoft.Resources/templateSpecs/versions', 'storageSpec', '1.0')]"
},
"parameters": {
},
"mode": "Incremental"
}
}
]
}
In the template, templateSpecRG is the name of the resource group that contains the template spec, storageSpec is the name of the template spec, and 1.0 is the version of the template spec.
Use Azure CLI or PowerShell to create a new resource group for the storage account.
New-AzResourceGroup `
-Name storageRG `
-Location westus2
az group create \
--name storageRG \
--___location westus2
Deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName storageRG `
-TemplateFile "C:\Templates\deployTemplateSpecV1.json"
az deployment group create \
--resource-group storageRG \
--template-file "C:\Templates\deployTemplateSpecV1.json"
Verify the deployment with Azure CLI or PowerShell.
Get-AzResource `
-ResourceGroupName storageRG
az resource list \
--resource-group storageRG
Grant access
To let other users in your organization deploy your template spec, grant them read access. Assign the Reader role to a Microsoft Entra group for the resource group that contains the template specs you want to share. For more information, see Tutorial: Grant a group access to Azure resources using Azure PowerShell.
Update template
To make a change to the template in your template spec, revise the template. The following template is similar to your earlier template except it adds a prefix for the storage account name. Copy the following template and save it as createStorageV2.json file.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string",
"defaultValue": "[format('store{0}', uniqueString(resourceGroup().id))]"
},
"___location": {
"type": "string",
"defaultValue": "[resourceGroup().___location]"
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-01-01",
"name": "[parameters('storageAccountName')]",
"___location": "[parameters('___location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"accessTier": "Hot"
}
}
]
}
Update template spec version
Instead of creating a new template spec for the revised template, add a new version named 2.0
to the existing template spec. You can choose either version to deploy.
Create a new version for the template spec.
New-AzTemplateSpec `
-Name storageSpec `
-Version "2.0" `
-ResourceGroupName templateSpecRG `
-Location westus2 `
-TemplateFile "C:\Templates\createStorageV2.json"
To deploy the new version, get the resource ID for the 2.0
version.
$id = (Get-AzTemplateSpec -ResourceGroupName templateSpecRG -Name storageSpec -Version "2.0").Versions.Id
Deploy that version. Provide a prefix for the storage account name.
New-AzResourceGroupDeployment `
-TemplateSpecId $id `
-ResourceGroupName storageRG `
-namePrefix "demoaccount"
Create a new version for the template spec.
az ts create \
--name storageSpec \
--version "2.0" \
--resource-group templateSpecRG \
--___location "westus2" \
--template-file "C:\Templates\createStorageV2.json"
To deploy the new version, get the resource ID for the 2.0
version.
id=$(az ts show --name storageSpec --resource-group templateSpecRG --version "2.0" --query "id")
Deploy that version. Provide a prefix for the storage account name.
az deployment group create \
--resource-group storageRG \
--template-spec $id \
--parameters namePrefix='demoaccount'
Open the template spec storageSpec, select Create new version.
Select 1.0 as the base template, and then select Create.
Name the new version 2.0
and optionally add notes. Select Edit template.
Replace the contents of the template with the updated template. Select Review + Save.
Select Save changes.
To deploy the new version, select Versions.
Open the new version, and then select Deploy.
Fill in the fields as you did when deploying the earlier version.
Select Review + create, and then select Create.
Again, you must make some changes to your local template to make it work with template specs. Copy the following template and save it locally as createTemplateSpec.json.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Resources/templateSpecs",
"apiVersion": "2022-02-01",
"name": "storageSpec",
"___location": "westus2",
"properties": {
"displayName": "Storage template spec"
}
},
{
"type": "Microsoft.Resources/templateSpecs/versions",
"apiVersion": "2022-02-01",
"name": "[format('{0}/{1}', 'storageSpec', '2.0')]",
"___location": "westus2",
"properties": {
"mainTemplate": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string",
"defaultValue": "[format('store{0}', uniqueString(resourceGroup().id))]"
},
"___location": {
"type": "string",
"defaultValue": "[resourceGroup().___location]"
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2025-01-01",
"name": "[[parameters('storageAccountName')]",
"___location": "[[parameters('___location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"accessTier": "Hot"
}
}
]
}
},
"dependsOn": [
"storageSpec"
]
}
]
}
To add the new version to your template spec, deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName templateSpecRG `
-TemplateFile "C:\Templates\createTemplateSpec.json"
az deployment group create \
--resource-group templateSpecRG \
--template-file "C:\Templates\createTemplateSpec.json"
verify the deployment with Azure CLI or PowerShell.
Get-AzTemplateSpec `
-ResourceGroupName templateSpecRG `
-Name storageSpec
az ts show \
--resource-group templateSpecRG \
--name storageSpec
You should see the new version 2.0
in the list of versions.
Copy the following template and save it locally to a file named C:\Templates\deployTemplateSpecV2.json.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2025-04-01",
"name": "demo",
"properties": {
"templateLink": {
"id": "[resourceId('templateSpecRG', 'Microsoft.Resources/templateSpecs/versions', 'storageSpec', '2.0')]"
},
"parameters": {
},
"mode": "Incremental"
}
}
]
}
Deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName storageRG `
-TemplateFile "C:\Templates\deployTemplateSpecV2.json"
az deployment group create \
--resource-group storageRG \
--template-file "C:\Templates\deployTemplateSpecV2.json"
Verify the deployment with Azure CLI or PowerShell.
Get-AzResource `
-ResourceGroupName storageRG
az resource list \
--resource-group storageRG
You should see the new storage account with a name that starts with store
and a unique string based on the resource group ID.
Clean up resources
To clean up the resource you deployed in this quickstart, delete both resource groups that you created.
- From the Azure portal, select Resource group from the left menu.
- Enter the resource group name (templateSpecRG and storageRG) in the Filter by name field.
- Select the resource group name.
- Select Delete resource group from the top menu.
Next steps
To learn about creating a template spec that includes linked templates, see Create a template spec of a linked template.