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.message

Key Properties

PropertyPurpose
kindAzureCLI or AzurePowerShell
azCliVersionVersion of the Azure CLI for the script
scriptContentThe script text, written inline
retentionIntervalHow long Azure keeps script resources, in ISO 8601 form such as PT1H
cleanupPreferenceWhen Azure removes helper resources: Always, OnSuccess, or OnExpiration
timeoutMaximum 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.