Bicep Deployment Scripts
A deployment script runs a short Azure CLI or PowerShell program as a step inside a Bicep deployment. Some tasks have no matching resource type, such as seeding data, fetching a value from another system, or running a one-time setup. A deployment script covers those gaps.
Think of a hotel that hires a helper for one morning. The helper arrives, finishes a checklist, reports the results, and leaves. The deployment script follows the same life cycle.
What Happens During a Script Run
Bicep deployment
│
▼
Azure starts a temporary container
│ runs your script with the identity you provide
▼
Script writes results to $AZ_SCRIPTS_OUTPUT_PATH
│
▼
Container is cleaned up ──► results flow back as outputs
A Basic Script
The resource type is Microsoft.Resources/deploymentScripts. The kind property selects the Azure CLI or Azure PowerShell. A user-assigned managed identity supplies the permissions.
param location string = resourceGroup().location
resource scriptIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: 'id-script'
location: location
}
resource helloScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
name: 'script-hello'
location: location
kind: 'AzureCLI'
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${scriptIdentity.id}': {}
}
}
properties: {
azCliVersion: '2.52.0'
retentionInterval: 'PT1H'
cleanupPreference: 'OnSuccess'
timeout: 'PT10M'
scriptContent: '''
echo '{"message":"setup complete"}' > $AZ_SCRIPTS_OUTPUT_PATH
'''
}
}
output scriptMessage string = helloScript.properties.outputs.messageKey Properties
| Property | Purpose |
|---|---|
| kind | AzureCLI or AzurePowerShell |
| azCliVersion | Version of the Azure CLI for the script |
| scriptContent | The script text, written inline |
| retentionInterval | How long Azure keeps script resources, in ISO 8601 form such as PT1H |
| cleanupPreference | When Azure removes helper resources: Always, OnSuccess, or OnExpiration |
| timeout | Maximum run time |
Return Values
A script reports results by writing JSON to the file named in the AZ_SCRIPTS_OUTPUT_PATH variable. Bicep reads the result through properties.outputs, and other resources use it as an input.
Pass Arguments and Environment Variables
properties: {
arguments: '-name shop'
environmentVariables: [
{
name: 'APP_ENV'
value: 'dev'
}
{
name: 'API_TOKEN'
secureValue: apiToken
}
]
// other settings omitted
}The secureValue field hides a secret from logs, while value shows plain text.
Use External Script Files
Short scripts fit inline. Longer scripts live in separate files that Bicep loads at compile time.
scriptContent: loadTextContent('scripts/setup.sh')Cautions
Grant Minimal Rights
The script identity needs only the permissions its commands require.
Plan for Re-Runs
Write scripts so a second run causes no harm. Azure may run the script again when the deployment repeats.
Expect Extra Resources
Azure creates a storage account and a container instance to run the script. Both disappear according to the cleanup setting, and both can add small costs while they exist.
When to Choose a Script
Reach for a resource type first. Native Bicep resources are faster, cheaper, and easier to preview with what-if. A script fits only when Azure has no resource type for the task. Typical cases include loading starter data into a database, registering an application in another system, and reading a value that Bicep cannot read directly. Keep scripts short and focused so reviewers understand them at a glance.
Summary
Deployment scripts run CLI or PowerShell steps inside a Bicep deployment. A managed identity grants permissions, the script writes results to AZ_SCRIPTS_OUTPUT_PATH, and Bicep reads them as outputs. Idempotent scripts, minimal rights, and a cleanup preference keep deployments tidy.
