AWS Deployment

  • Page Owner: Not Set
  • Last Reviewed: 2025-08-26

Install the Azure Deployment Group‌

First you'll need to install DevOps' deployment agent on the target server. You do this by getting a PowerShell script from the Azure DevOps administration.‌

  1. Log into DevOps and go to the Organization Settings

  2. In the Settings area, go to the Deployment Pools page

  3. Add new pool, give it a sensible name, check the project(s) for which this target will be used. Azure will automatically create corresponding deployment pools in those projects.

  4. On the next page, check the "Use Personal Access Token", and then click the "Copy script to the clipboard" button. (Note: Do not copy/paste the script you see before you, as this may not have your PAT included)

  5. RDP into the target server, start PowerShell as administrator, and paste in the script. (Note: The script doesn't appear to work with PowerShell 6 at the time of this writing)

  6. Press enter to use SYSTEM as the account the agent runs as.‌

Add the nuget.config file‌

If you're using any Blend packages, hosted on the Blend nuget server, you'll need a nuget.config file that lists the Blend nuget feed. This should be in the same folder as your Solution file. For Episerver sites, you'll also need to list Episerver as a source.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
    <add key="Blend Interactive" value="http://nuget.blendinteractive.com/nuget" />
    <add key="EPiServer" value="https://nuget.episerver.com/feed/packages.svc/" />
  </packageSources> 
</configuration>

‌Create the appropriate Web.config transform file‌

This will vary by project, but you should have a Web.config transform file for each environment that requires it. For example, a QA environment might include:

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
 <connectionStrings>
 <add name="EPiServerDB" connectionString="Data Source=.;Initial Catalog=Episerver;Integrated Security=False;User ID=blend;Password=XXXXXXX;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" xdt:Transform="Replace" xdt:Locator="Match(name)" />
 </connectionStrings>
 <solr>
 <server id="SOLR" url="http://localhost:8983/solr/project" documentType="Project.Business.Solr.SearchDocument, Project" xdt:Transform="Replace" xdt:Locator="Match(id)" />
 </solr>
 <appSettings>
 <add key="site:GoogleMapsServerApiKey" value="XXXXXXXXXXXX" xdt:Transform="Replace" xdt:Locator="Match(key)" />
 </appSettings>
 <system.net>
 <mailSettings xdt:Transform="Replace">
 <smtp from="info@blendinteractive.com">
 <network host="smtp.mailtrap.io" port="465" userName="XXX" password="XXX" /> <!-- AWS throttles port 25 --> 
 </smtp>
 </mailSettings>
 </system.net>
 <episerver>
 <applicationSettings uiMaxVersions="1" xdt:Transform="SetAttributes(uiMaxVersions)" />
 </episerver>
 <system.web>
 <compilation debug="true" xdt:Transform="SetAttributes(debug)"/>
 <customErrors xdt:Transform="Remove"/>
 <customErrors mode="Off" xdt:Transform="InsertIfMissing" />
 <httpRuntime maxRequestLength="1048576" xdt:Transform="SetAttributes(maxRequestLength)" />
 </system.web>
 <system.webServer>
 <security xdt:Transform="Remove" />
 <security xdt:Transform="InsertIfMissing">
 <requestFiltering>
 <requestLimits maxAllowedContentLength="1073741824"/>
 </requestFiltering>
 </security>
 <rewrite xdt:Transform="Remove" />
 </system.webServer>
</configuration>

Put this file in the same location as the site's Web.config file. Add it to the csproj file as a dependency on the Web.config file. It should look like this:

 <Content Include="Web.QA.config">
 <DependentUpon>Web.config</DependentUpon>
 </Content>

You may need to add files for environment-specific items like robots.txt and license files as well. These files will get put into place during the build pipeline.‌

Add the azure-pipelines.yml file

Create an azure-pipelines.yml file in the root of your project. The content should be similar to the following:

trigger:
- qa
 
pool:
 vmImage: 'windows-latest'
 
variables:
 solution: './PROJECT.sln'
 buildPlatform: 'Any CPU'
 buildConfiguration: 'Release'
 
steps:
- task: NuGetToolInstaller@1
 
- task: NuGetCommand@2
 inputs:
 command: 'restore'
 restoreSolution: '$(solution)'
 feedsToUse: 'config'
 nugetConfigPath: '$(Build.SourcesDirectory)/nuget.config'
 
- task: xdttransform@3
 inputs:
 workingFolder: './Project/'
 transforms: 'web.qa.config => web.config'
 
- task: PowerShell@2
 inputs:
 targetType: 'inline'
 script: |
 Copy-Item .\Project\License.qa.config .\Project\License.config -Force
 Copy-Item .\Project\robots.qa.txt .\Project\robots.txt -Force
 
- task: VSBuild@1
 inputs:
 solution: '$(solution)'
 msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"'
 platform: '$(buildPlatform)'
 configuration: '$(buildConfiguration)'
 
- task: PublishSymbols@2
 inputs:
 SearchPattern: '**/bin/**/*.pdb'
 PublishSymbols: false
 
# Creates a build artifact and stores it in Azure
- task: PublishBuildArtifacts@1
 inputs:
 PathtoPublish: '$(Build.ArtifactStagingDirectory)'
 ArtifactName: 'Project.QA'
 publishLocation: 'Container'
 
# This posts to Slack, update things that say CHANGEME and Project based on the name of the project.
# Also pick appropriate icons
# This only handles the failure case, because the success slack will be sent once the release is deployed.
- task: PowerShell@2
 inputs:
 targetType: 'inline'
 script: |
 # Build FAILED
 $payload = @{ 
 "icon_emoji" = ":blend:"
 "text" = "Project QA build failed | <https://dev.azure.com/BlendInteractive/CHANGEME/_build/results?buildId=$($env:Build_BuildId)&view=logs|View Log>"
 "username" = "Azure DevOps (Project)"
 }
 
 # Powershell uses TLS 1.0 by default, which AWS sensibly refuses to use.
 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
 Invoke-WebRequest `
 -Body (ConvertTo-Json -Compress -InputObject $payload) `
 -Method Post `
 -UseBasicParsing `
 -Uri "https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX" | Out-Null
 condition: failed()

This file builds the project and stores the build as an artifact in Azure.‌

Commit all the new and updated files and merge to master.‌

Create the Pipeline in Azure‌

Finally, with all this set up, you can create a pipeline to run the build.

  1. Go to Pipelines -> New Pipeline

  2. Choose Azure Git as your source

  3. Select the repository for your project

  4. Select "Existing Azure Pipeline YAML" at the bottom

  5. Choose the branch you want to deploy, and the path to the azure-pipelines.yml

Build the pipeline‌

You'll need at least one artifact to deploy.‌

Create the Release in Azure‌

The pipeline above only creates a release, but does not actually deploy it. For that step, we need to use a Release.‌

  1. Go to the Releases section of your project's Pipelines in Azure.

  2. Create a New Release Pipeline, select Empty Job as your template.

  3. Give it a sensible name.

  4. Click "Add Artifiact" and select the artifact you just built.

  5. For a QA build, you can select the "lightning bolt" icon and enable continuous integration.

  6. Save the pipeline.

  7. In the first stage, select tasks.

  8. Remove the "Agent Job". You don't need to run anything on any Azure agents.

  9. In the Deployment Process, add a new "Deployment Group job". These jobs run on the server you're deploying to, which is what we need to deploy files to IIS.

  10. Give the job a sensible name (such as Deploy to IIS)

  11. Select the appropriate deployment group

  12. Now add a "IIS Deploy" task to the deployment group job. Give it the correct IIS Site name. Probably check "Remove files at destination" (unless you have reason not to), and possibly check Take App Offline.

  13. Finally, add a Powershell task to post the success result to slack. Follow the guidance here.