Automating deployments to Azure IaaS with custom actions

Firstly the final scripts of all the content discussed are available here. A video walkthrough is available at and included below.

In this post I want to document the results of a POC (proof of concept) I was engaged in for a very large customer. The customer wanted to create single/multi VM environments in Azure for dev/test/QA purposes. The goal was a single command execution that would create the VM and in this case make it a domain controller, install SQL Server 2012 then install SharePoint 2010. For this scenario I decided to use PowerShell rather than JSON just to demonstrate the PowerShell approach since there are already many JSON templates in the gallery around SharePoint deployment.

To enable this solution the high level workflow would be:

  1. Create a new resource group and in that create a new storage account and virtual network (since each environment was to be isolated and by placing in their own resource group the lifecycle management, i.e. deletion, would be simple)
  2. Create a new VM using the created resources
  3. Execute PowerShell inside the VM via the Azure VM Agent to promote the VM to a domain controller then reboot it
  4. After the reboot execute additional PowerShell to create accounts, open firewall exceptions, install SQL Server 2012 then install SharePoint 2010

The unattended installation of a domain controller via PowerShell is very simple. Below is an example that creates a pocdom.local domain.

You will notice in the code I write the AD to the E: drive. This is because in Azure the OS disk by default is read/write cache enabled which is not desirable for databases. Therefore for the VM I add two data disks with no caching; one for AD and one for SQL and SharePoint. The code below is what I use to change the drive letter of the DVD device then initialize and format the two data disks.

The two pieces of code above would be combined into the first boot PowerShell code (with the disk initialization block before the DC promotion code). Once the reboot has completed firewall exceptions for SQL and SharePoint need to be enabled.

Next I need the SQL Server and SharePoint media along with unattended commands to install. I decided to use Azure Files as the store for the installation media. Azure Files presents an SMB file share to the VMs with only the storage account key and name required to access. In my example I place this in the PowerShell script however it could also be injected in at runtime or stored more securely if required. Create a storage account then create an Azure Files share through the portal and take a note of the access key and storage account name.


Into this share I will copy the SQL Server and SharePoint installation files. The easiest way to upload content is using the free Azure Storage Explorer tool from

Now the details of performing unattended installations of SQL and SharePoint are outside the scope of this write-up as the goal for this is more how to install applications through Azure IaaS PowerShell however at a very high level:

  • To install SQL Server unattended simply requires a configuration file which can be generated by running through the graphical SQL Server setup and on the last page it will show you the location of the configuration file it will use for installation. Simply copy this file and cancel the installation. Copy the SQL Setup structure and the configuration file to the Azure Files share. I place the ConfigurationFile.ini in a separate Assets folder on the share. Then use that setup file with the SQL setup.exe, for example
  • For the SharePoint unattended installation I used the autospinstaller solution which is fully documented at and includes a web based site to create the unattended answer file used by the program. Follow the instructions on the site and copy the resulting structure to the Azure Files share.

My resulting Azure Files share consists therefore of 3 folders:

  • AutoSPInstaller – The SharePoint installation media and AutoSPInstaller solution
  • POCAzureScripts – The SQL configuration script
  • SQLServer2012SP3 – SQL Server installation media

To map to the share, copy the content, trigger the SQL Server installation from the share, dismount the share then trigger the SharePoint installation I use the following (which also adds an account named Administrator as that was a requirement). I would add the firewall exception creation to this code as the secondboot PowerShell file. You will notice I wait for 40 minutes at the end for the SharePoint installation to complete. I run the SharePoint install as a separate, asynchronous job as at the end it asks for key presses to continue so this avoids trying to handle that and after a reboot that will all get cleared up.

At this point I have a firstboot.ps1 and a secondboot.ps1 file. Upload those files into blobs in a container named scripts in the same storage account as the Azure Files. These files will be used as part of the total VM provisioning process.

The final part is to create the VM and use the PowerShell created. In the example code below I create all the resources and use premium storage accounts to maximum performance however any of these parameters can be changed to meet requirements. In the code replace the <storage account name for assets> with the storage account created holding the Azure Files and blob content along with its key. Also change the VM name to something unique since a public IP name will be generated based on this name. If you will deploy this many times add some logic to include some random sequence or perhaps the requesting username. Also include that as part of the resource group, storage account etc name.

In this example I give the VM a public IP so it can be accessed externally and has no NSG to lock down traffic. In reality you may not want the public IP and may add the environment to existing networks with connectivity to on-premises so would connect via private IP but I added public IP to handle worst case connectivity. If you do add a public IP like this example don’t use administrator account and don’t set simple passwords and make sure you configure NSGs to at least lock down traffic. I talk about NSGs at and below is example ARM PowerShell to create and add an NSG to a NIC.

Finally if you want to delete the entire environment just run:


Tags: ,

Comments are closed.