Azure VM Extensions: Part 1 DSC Extensions

This blog post covers some of the battles I have had trying to install some software onto a VM within Azure. There are many ways to go about this and at the end of the day, yeah you live to fight another day.

High level requirements:

1 – Install Octopus Deploy Tentacle onto a VM and have the agent running.
2 – Install Zabbix Agent (which is a windows service) onto the same VM and ensure the service starts correctly. (I’ll cover this in part 2 of the blog post).

Now as said previous, many ways to do this, I looked up what is available from Octopus Deploy as they always have good stuff, they used to have an Azure Extension you could use but they binned that off in favour of PowerShell DSC. I have never used PowerShell DSC, so I’m game for learning anything I know nothing about. Turns out they have the PowerShell DSC available to download and so I just needed to write the Bicep that grabs this from an Azure storage account and away we go…

I have the Bicep for creating the VM and I let that do its thing and decide to create a separate module for the VM DSC extension. So I grab the zip file from Octopus Deploy and read thru the code etc and all good and then I add this to my Azure storage account manually and now I need to figure out the Bicep code within the extension to download the zip file and have it run. The issue I run into is that the Azure storage account isn’t public so I need to figure out on how to generate a SAS token from the storage account and use that to be able to grab the file from storage and download it to the VM.

In order to get a SAS token out for all blobs (might not be what you want so be careful) you can do something like this:-

var allBlobDownloadSAS = listAccountSAS(, '2022-09-01', {
  signedProtocol: 'https'
  signedResourceTypes: 'sco'
  signedPermission: 'rl'
  signedServices: 'b'
  signedExpiry: '2024-01-01T00:00:00Z'

output sasToken string = allBlobDownloadSAS

So this would be part of the storage account module and just use the SAS token like so:-

var DSCSAS = storageAccount.outputs.sasToken

Now here comes the bit to pay attention too. The Bicep for the VM Extension is as follow, now the URL only worked for me if I appended the SAS token at the end, I don’t want to make the storage account publicly accessible so I needed the SAS token

@description('Add the Octopus Deploy Tentacle to the Backend VM') 
module vmName_dscExtension_OctopusDeployExtension './modules/Microsoft.Compute/virtualMachines/extensions/deploy.bicep' =  if (addVirtualMachine) { 
  scope: resourceGroup(myResourceGroupName) 
  name: 'vmName_dscExtension' 
  params: { 
    autoUpgradeMinorVersion: true 
    enableAutomaticUpgrade: false 
    name: 'vmName_dscExtension' 
    publisher: 'Microsoft.Powershell' 
    type: 'DSC' 
    typeHandlerVersion: '2.77' 
    virtualMachineName: virtualMachineNameBackend 
    location: location 
    settings: { 
      configuration: { 
                  url: 'https://${storageAccountName}${containername}/${DSCSAS}' 
        script: 'OctopusTentacle.ps1' 
        function: 'OctopusTentacle' 
      configurationArguments: { 
        ApiKey: tentacleApiKey 
        OctopusServerUrl: tentacleOctopusServerUrl 
        Environments: tentacleEnvironments 
        Roles: tentacleRoles 
        ServerPort: tentaclePort 
  dependsOn: [ 

No doubt you can do this with a Managed Identity but I couldn’t get it working and had spent a LOT of time on this so gave up and used the SAS token instead.

The DSC extension takes care of unzipping the files onto the VM and running the PowerShell script called OctopusTentacle.ps1

In summary this is how you can create a SAS Token in Bicep from a storage account and also how you can reference a blob in the storage account and install it.
I realise the way I am doing this might not be best so if you find an alternative or have feedback do please let me know.

Don’t forget to subscribe to my YouTube Channel. And my Newsletter