Setting Up Azure Deployment Slots for Multi-Tenant SXA
Utilizing Deployment Slots in Azure is a great way to achieve a zero-downtime deployment process. The idea is to have an environment (e.g. Production) extend another semi-environment (e.g. Staging) that gets deployed to and then later swapped to deliver the site updates in no time. But how do we set this up especially in the context of a multi-tenant Sitecore SXA project?
Add a Deployment Slot
- Login to Azure Portal. Navigate to the App Service you are setting up for a zero-downtime (e.g. production-123456-cd) and on the Resource Menu (sidebar) under the Deployment section, click Deployment Slots.
- You will see the listed Deployment Slots and a column to tell how much traffic is allocated to what.
- Click the + Add Slot button.
- A side dialog box appears and name your deployment slot. In this example, give it a name “stage“. Notice that it also shows how the Azure domain would look like.
- Then in the Clone settings from dropdown menu, choose the source slot. In this case, the only existing one.
Populate the New Deployment Slot
- After clicking Add, you will be provisioned with another App-Service like environment that you can navigate on. This environment will contain similar menus you see in the source slot but here, the difference is that it runs in another file-system container. Click on the newly created Deployment Slot and you will notice a new view with a way to determine that you are in a slot.
- This container is empty upon creation. If you do not have a complete packaged build with all of the /sitecore and related folders and not having the same state as Production’s, then it’s probably best to get the files from the source slot (cd) then copy it to stage. Transmittal can be done with various tools like FTP, Kudu Zip Deploy or SCP from one environment to another:
- App Service Backups – this is perhaps the easiest way to copy and paste the App Service files from source environment to another. If you have Automatic Backup enabled, follow the steps below:
- Go back to the source slot (cd) and on the Resources Menu, click on Backups under Settings section. You will see a bunch of automatically backed up files instances.
- On the latest backup, click the Restore icon button.
- Select the source App Service which by default is the current
- Point to the target Deployment Slot (in this case, the created stage). Restoring a backup will probably take up a long time because automatic backups copy all the files and folders from the App Service by default, meaning even the large /App_Data or /temp folders are being restored, unless you particularly exclude these folders using a Backup Filter.
- App Service Backups – this is perhaps the easiest way to copy and paste the App Service files from source environment to another. If you have Automatic Backup enabled, follow the steps below:
- FTP and Kudu Zip Deploy – this is perhaps the go-to approach of many developers because it gives more control and visual orientation over which files and folders are we going to transmit. Downside is, it could take up more time from you to do the steps and monitor the progress. Since this is just an alternative, feel free to follow any approach that might be easier or faster. Here are the steps:
- Establish an FTP connection. From the source App Service (CD), under the Resource Menu > Deployment section, click Deployment Center. Then on the content area, click the tab called FTPS credentials.
- Copy the credentials found here and paste it in your favorite FTP tool to create a connection setting. My favorite FTP tool that I use is FileZilla.
- Connect to this App Service and download the Sitecore site files and folders to your local machine, but this time, exclude the /App_Data and /temp folders.
- After finishing the download, package all the files and folders into a zip file.
- Then in the target slot (stage), under the Resource Menu >Development Tools, click Advanced Tools > Go. This will fire up another tab titled Kudu Services. Under the Navigation, click Tools > Zip Push Deploy.
- This will load up a page with files listing. Just drag and drop the zip file you have created and it will automatically extract and replenish the files and folders upon upload.
- Optional: For prudence’ sake, create the folders /App_Data and /temp. I know it gets automatically created by Sitecore, but hey, it doesn’t hurt to create even the main child folders under /App_Data.
Map Custom Domains to SXA
Once you have populated the new Deployment Slot with the same files from the Production, it’s time to map some Custom Domains on this stage to the tenant sites in SXA.
- If in your current set up, your company provides a development domain (*.devcompany.com) that can be extended for unlimited subdomain registrations, then that is better.
- First, create these stage-appended CNAME entries in your DNS registry or cloud hosting provider where you manage these subdomains. These will later be mapped to your SXA tenant sites. So for instance, you have the following sites project-abc.devcompany.com and deliverable-123.devcompany.com, then add another set for project-abc-stage.devcompany.com and deliverable-123-stage.devcompany.com
- DO NOT forget to point these CNAME entries to the created Deployment Slot Assigned Custom Domain. To locate where this piece of info can be found, under the stage Deployment Slot Resource Menu >Settings, click Custom domains. This can be found in a light disabled text style.
- Go back to the stage Deployment Slot and under Resource Menu > Settings > Customdomains, click + Add custom domain button. Validate and add these new subdomains and attach an SSL Certificate. See related article: Host SXA Site in Azure with AWS Subdomain.
- Once the Subdomains are added as Custom Domains, now in CM add the same entries to the SXA Tenant Site Grouping together with the live domain as pipe-delimited. Publish these Site Grouping items per tenant. Access these stage subdomains in your browser and you should see the site up.
- Errors like this one here occur when there’s a discrepancy between your /App_Config and /bin files to that of the CM. So in order to fix this, ensure that the assemblies in CM, CD and stage Deployment Slot are in sync.
Server Error in '/' Application. A route named 'sxa' is already in the route collection. Route names must be unique. Parameter name: name Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.ArgumentException: A route named 'sxa' is already in the route collection. Route names must be unique. Parameter name: name Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [ArgumentException: A route named 'sxa' is already in the route collection. Route names must be unique. Parameter name: name] System.Web.Routing.RouteCollection.Add(String name, RouteBase item) +392 System.Web.Http.RouteCollectionExtensions.MapHttpRoute(RouteCollection routes, String name, String routeTemplate, Object defaults, Object constraints, HttpMessageHandler handler) +231 Sitecore.XA.Feature.Search.Pipelines.Initialize.InitializeRouting.Process(PipelineArgs args) +444 (Object , Object ) +9 Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +490 Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists) +236 Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) +22 Sitecore.Nexus.Web.HttpModule.Application_Start() +215 Sitecore.Nexus.Web.HttpModule.Init(HttpApplication app) +1184 System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +584 System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +168 System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +277 System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +369 [HttpException (0x80004005): A route named 'sxa' is already in the route collection. Route names must be unique. Parameter name: name] System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +532 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +111 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +724
Finally, this new Deployment Slot is now ready to accept new builds without affecting the Live site. After deploying the release, just swap the slots. There you go, zero-downtime!