Thursday, November 23, 2017

Deploying Sitecore 9 to Azure PaaS with Sitecore Azure Toolkit

While there is bunch of documentation available to get started with Sitecore deployment on Azure PaaS, I am sharing my experience of deploying a simple Sitecore 9 deployment topology (XPSingle).

For you to be able to deploy Sitecore 9 on Azure PaaS you need few pre-requisites. These are well documented by Sitecore and you can refer it in the Sitecore Azure Toolkit documentation.

Since most of the pre-requisites were in place for me here are few things you need to get started

Sitecore Azure Toolkit 2.0 

  • Download the zip, Unblock it, and unzip it in an appropriate place in your file system.
  • You can import the Powershell module from Sitecore.Cloud.Cmdlets.psm1 in tools directory and explore the command-lets

Sitecore 9 Web deployment packages

  • Based on the topology you want to deploy, download the web deploy packages (scwdp files) from Sitecore download portal. In my case it is Sitecore 9 XPSingle and I downloaded two packages (one for sitecore - Sitecore 9.0.0 rev. 171002 (Cloud) and another is for xConnect  - Sitecore 9.0.0 rev. 171002 (Cloud)
  • As we will need these packages accessible over internet, upload these packages in an Azure blob storage account under container named based on your convenience. Please review the type of container and your access requirements. In my case, since I was experimenting, I kept it publicly accessible.

ARM templates

  • Download azuredeploy.parameters.json template from github.
  • I preferred the released version Sitecore Azure Quickstart Templates 2.0 (, but you may want to refer the latest from the repository
  • Sitecore Azure Toolkit commandlets passes parameters to Azure ARM template to provision your infrastructure and hence you need to have only the azuredeploy.parameters.json file on your local machine.
  • As a best practice, I would suggest you to deploy your ARM templates in your own repository OR azure storage which is accessible over internet as this will not have any impact of changes done on git and you are working against a stable template.


Create a pkcs 12 self-signed certificate file as give below (use Powershell command prompt in administrative mode - for some reason powershell ISE did not work for me).

Please note: I did it for on-premise deployment of Sitecore 9 to secure Solr instance but same file would do if you want to avoid creating new one.

-genkeypair -alias solr-ssl -keyalg RSA -keysize 2048 -keypass secret
-storepass secret -validity 9999 -keystore solr-ssl.keystore.jks -ext
SAN=DNS:localhost,IP: -dname "CN=localhost, OU=Organizational
Unit, O=Organization, L=Location, ST=State, C=Country"

keytool -importkeystore -srckeystore solr-ssl.keystore.jks -destkeystore solr-ssl.keystore.p12 -srcstoretype jks -deststoretype pkcs12

Now since this is a self-signed certificate and not from a trusted auhority, you also need to inclued an additional parameter in azuredeploy.parameters.json file as below

    "allowInvalidClientCertificates": {
      "value": true

You can also refer the whole walkthrough and more details of the entire deployment process here -> Walkthrough: Deploying a new Sitecore environment to the Microsoft Azure App service

Deployment Script

Once you have everything in place, create a new Powershell script in Windows Powershell ISE (in administrative mode). Replace values with you own setup (refer comments for each line) and start deploying

##Path to Sitecore Azure Toolkit commandlet script that you will be importing

$SCAzToolkitPath = "C:\Sitecore9\Azure\Sitecore Azure Toolkit 2.0.0 rev.171010\tools\Sitecore.Cloud.Cmdlets.psm1"

##this is the name used for creating a resource group on azure and also will be a prefix for lot of services.
##Keep it small case with letters and numbers only. Follow azure resource naming rules.
$DeploymentId = "sc9xpsingle"

##Certificate .p12 file created using keytool. Replace it with your physical location
$CertFile = "C:\Sitecore9\Azure\Certificate\solr-ssl.keystore.p12"

##Path to your license file
$LicenseXmlPath = "C:\MyWork\Sitecore\License\license.xml"

##Deployment region - Refer Sitecore Azure deployment compatibility matrix here
$Location = "East US"

##Your azure subscription ID, copy it from your azure portal by navigating it to subscription and selecting appropriate subscription under which you want to deploy your instance
$SubscriptionId = "4dfeb08c-7e41-40af-a9fa-fabcac401c2d"

##This has to be internet addreseable URL otherwise you face errors as shown in gotcha 1.
$ARMTemplate = ""

##This is a physical (local) path
$ARMParametersTemplate = "C:\Sitecore9\Azure\Sitecore-Azure-Quickstart-Templates-2.0\Sitecore-Azure-Quickstart-Templates-2.0\Sitecore 9.0.0\XPSingle\azuredeploy.parameters.json"

##Set the parameters that needs to be passed to the ARM templates
##Please note that I have uploaded the deploy packages on azure storage at a particular location, your location may vary

$Parameters = @{
    "authCertificateBlob" = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes($CertFile));
    "singleMSDeployPackageUrl" = "https://<storageaccount>";
    "xcSingleMsDeployPackageUrl" = "https://<storageaccount>";
    "authCertificatePassword" = "secret";
    "sitecoreAdminPassword" = "Passw0rd";
    "sqlServerLogin" = "badal";
    "sqlServerPassword" = "Passw0rd"; ##ensure you have the password according to SQL Azure password policy ->
    "location" = $Location;
    "deploymentId" = $DeploymentId

##Import your Sitecore Azure Toolkit commandlets
Import-Module -verbose $SCAzToolkitPath

Add-AzureRmAccount ##Add-AzureAccount will not work

Set-AzureRmContext -SubscriptionId $SubscriptionId

##make sure you use -verbose to see the output of deployment status as it happens
Start-SitecoreAzureDeployment -verbose -Location $Location `
                                -LicenseXmlPath $LicenseXmlPath `
                                -SetKeyValue $Parameters `
                                -Name $DeploymentId `
                                -ArmTemplatePath $ARMTemplate `
                                -ArmParametersPath $ARMParametersTemplate

Deployment takes about 20-30 mins. Once your deployment is successful, you can login to sitecore as you would normally on your local deployment. In Azure, It deployes about 19 resources (app service plan, Azure App, Azure Search, SQL Databases, Redis Cache and bunch of others) as shown below

Sitecore Azure Resources for XP Single deployment topology

Few Gotchas / Errors I faced

1. Phyical path Vs URL for your azure template
I had given the physical path of my azuredeploy.json template and azure could not identify the nested templates during deployment. I got this error below and I changed it to the internet addressable path

'The template resource 'templateLinkBase' at

line '28' and column '30' is not valid: The language expression property 'templateLink' doesn't

exist, available properties are 'template, parameters, mode, provisioningState'

2. When I changed the path, I also changed the path of the parameters template to internet addressable path and i got this error. Hence you need to have the parameters file (azuredeploy.parameters.json) on your local machine

Start-SitecoreAzureDeployment : A parameter cannot be found that matches parameter name 'Raw'.
At C:\Sitecore9\Azure\DeploymentScript\xpSingleDeploy.ps1:27 char:1
+ Start-SitecoreAzureDeployment -verbose -Location $Location `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Start-SitecoreA 
3. Ensure you execute your Start-SitecoreAzureDeployment commandlet with -verbose to get enough clues on whats going wrong

4. Also ensure you set the parameters key value pair in @parameter variable for deploymentId, and location as this did not seem to be passed though the command (as you can see I have done it at both places - especially for location). Also check other paramters as shown in the script above

5. I also gave deploymentID as something with capital letters, which was not accepted as a valid resource names for Azure hence keep it small case.