Deploy apps to Azure and Azure Stack

Applies to: Azure Stack integrated systems and Azure Stack Development Kit

This solution shows you how to deploy apps to Azure and Azure Stack by using Azure Pipelines hybrid continuous integration and continuous delivery (CI/CD).

After you set up Azure Stack, Azure DevOps, and web apps according to the Prerequisites, you can:

  • Register your web app and set up Azure Pipelines access in Azure Active Directory (Azure AD).
  • Create Azure Pipelines endpoints for Azure AD and Active Directory Federation Services (AD FS).
  • Install the Azure Pipelines build agent on the Azure Stack build server.
  • Configure self-contained app deployment to Azure and Azure Stack.
  • Create a build pipeline that runs automatic builds based on code commits to your project.
  • Create a release pipeline that automatically deploys your builds to both Azure AD and Azure Stack.
  • Manually create and deploy releases, and view release summaries and logs.

To learn more about CI/CD, see the following articles:

Azure Stack and hybrid CI/CD

Microsoft Azure Stack is an extension of Azure that brings the agility and innovation of cloud computing to your on-premises environment. It's the only hybrid cloud that lets you build and deploy hybrid apps in on-premises as well as public cloud environments. You can build an app on Azure Stack and then deploy it to Azure Stack, to Azure, or to your Azure hybrid cloud.

App deployment continuity, security, and reliability are critical elements for your organization and development team. The Azure Pipelines hybrid CI/CD delivery model lets you consolidate your build pipelines across your on-premises environment and the public cloud, and change deployment locations without changing your app. Other benefits of using the hybrid approach are:

  • You can maintain a consistent set of development tools across your on-premises Azure Stack environment and the Azure public cloud. A common tool set makes it easier to implement CI/CD patterns and practices.
  • Apps and services deployed in Azure or Azure Stack are interchangeable, and the same code can run in either location. You can take advantage of on-premises and public cloud features and capabilities.


The article Hybrid cloud design patterns for Azure Stack reviews software quality pillars for designing, deploying, and operating hybrid applications. The quality criteria include placement, scalability, availability, resiliency, manageability, and security. These design considerations assist in optimizing hybrid app design, minimizing challenges in production environments.


  • Basic knowledge of Azure and Azure Stack. To learn more before deploying this solution, read the following articles:

  • An Azure subscription. If you don't have one, create a free account before you begin.

  • A web app created in Azure. Use an Azure Resource Manager template to create a web app you can deploy both on-premises and to the public cloud. Make a note of the app URI to use later.

  • Visual Studio 2019 installed.

  • Admin access to an Azure DevOps organization that can create pipelines, and a DevOps project or workspace.

  • A Windows Server 2016 image with .NET 3.5 for the private build agent virtual machine (VM) Azure Pipelines builds on your Azure Stack.

  • An Azure Stack integrated system, or the Azure Stack Development Kit (ASDK) deployed and configured according to the following instructions.

    The Azure Stack Development Kit (ASDK) is a single-node deployment of Azure Stack you can download and use for free. The ASDK lets you evaluate Azure Stack and use Azure APIs and tooling in a non-production environment.

    Any user with Azure AD or Active Directory Federation Services (AD FS) admin credentials can deploy the ASDK. An Azure OEM/hardware partner can deploy a production Azure Stack. You must be an Azure Stack operator to do the following Azure Stack configuration tasks:

    • Deploy Azure App Service
    • Create plans and offers
    • Create a tenant subscription
    • Apply a Windows Server 2016 image


    The ASDK installation takes approximately seven hours, so plan accordingly.

    To deploy and configure the ASDK:

    1. Follow the detailed deployment instructions in Deploy the ASDK using the installer.

    2. Use the ConfigASDK.ps1 PowerShell script to automate ASDK post-deployment steps.

    3. Deploy Azure App Service PaaS services to Azure Stack.

    4. Create a plan and offer in Azure Stack.

    5. Create a tenant subscription to the offer in Azure Stack.

    6. Create a web app in the tenant subscription. Make note of the new web app URL for later use.

    7. Deploy a Windows Server 2016 VM with .NET 3.5 in the tenant subscription, to be the build server that runs Azure Pipelines.


    Your Azure Stack environment needs the correct images to run Windows Server and SQL Server. It must also have App Service deployed.

Register your web app and give it access to resources

In Azure Active Directory (Azure AD), Azure Pipelines authenticates against Azure Resource Manager using a service principal. To provision resources for Azure Pipelines, the service principal must have the Contributor role in the Azure subscription.

You can use the Azure portal to configure authentication for your app.

  1. Register your app to create a service principal.
  2. Use role-based access control (RBAC) to give the Service Principal Name (SPN) the Contributor role.
  3. Copy and save the Application ID and Tenant ID values you need to create endpoints for Azure Pipelines.
  4. Create and save an application secret key value.

You can also use a PowerShell script to create a Service Principal and endpoints. The article Create an Azure Resource Manager service connection with an existing service principal explains this process.


If you use the PowerShell script to create an Azure Stack Azure Resource Manager endpoint, you need to pass the -azureStackManagementURL parameter and -environmentName parameter. For example:
-azureStackManagementURL https://management.local.azurestack.external -environmentName AzureStack

Register your app in Azure AD

  1. In the Azure portal, select Azure Active Directory, and then select App registrations in the left navigation.

  2. Select New registration.

  3. On the Register an application page

    1. Enter your web app's name.

    2. Select a supported account type.

    3. Under Redirect URI, select Web for the type of application you want to create, and enter your web app's URI.

    4. Select Register.

      Register your application

Assign the app to a role

You must assign your application to a role for it to access resources in your subscription. Azure RBAC lets you control the level of access that users need to do their jobs. For more information about RBAC, see Manage access to Azure subscription resources. To learn about the available roles, see RBAC: Built-in roles.

Azure Pipelines must have the Contributor role to be able to provision resources in an Azure Stack subscription.

You can set the role scope at the subscription, resource group, or resource level. Permissions are inherited to lower levels of scope. For example, adding an app to the Reader role for a resource group means the app can read the resource group and any of its resources.

To assign your application to the Contributor role:

  1. In the Azure portal, navigate to the level of scope you want. For example, to assign a role at the subscription scope, select All services and Subscriptions.

    Assign a role at the subscription scope

  2. Select the subscription to assign the application to.

  3. In the left navigation, select Access control (IAM).

  4. Select Add a role assignment.

  5. In the Add role assignment dialog, select the Contributor role. By default, Azure AD applications aren't displayed in the available options. To find your application, search for the name and select it.

    Select the role and the application

  6. Select Save to finish assigning the role. You can see your application in the list of users assigned to a role for that scope.

Your service principal is set up. The next section shows how to get the values that Azure Pipelines needs to sign in programmatically.

Get values for signing in

When creating endpoints for Azure Pipelines, you need to enter the tenant ID and the application ID. To get those values:

  1. In the Azure portal, select Azure Active Directory.

  2. In the left navigation, select App registrations, and then select your application.

  3. Copy and save the Directory (tenant) ID and the Application (client) ID to use for creating endpoints.

    Copy the directory (tenant ID) and application (client) ID

Create a new application secret

When creating endpoints for Azure Pipelines, the app needs to authenticate. It can use a certificate or an application secret. If you deployed Azure Stack with AD FS as the identity provider, you must use a certificate.

Follow the steps in Certificates and secrets to create and upload a new certificate.

Or, to create a new application secret:

  1. In the Azure portal, select Azure Active Directory.

  2. In the left navigation, select App registrations, and then select your application.

  3. In the left navigation, select Certificates & secrets.

  4. Under Client secrets, select New client secret.

  5. In Add a client secret, type a description, select an expiration, and select Add.

  6. Copy the VALUE of the new secret. You need to provide the value to sign in as the app. It's important to save this value now, because it won't be displayed again after you leave this page.

    Copy the secret value because you can't retrieve it later

Create endpoints

By creating endpoints, an Azure Pipelines build can deploy Azure AD apps to Azure Stack. Azure Pipelines connects to the build agent, which connects to Azure Stack.

After setting endpoint creation permissions, you can create endpoints for Azure AD or AD FS.

  • If you deployed Azure Stack with Azure AD as the identity provider, you can use a certificate or application secret to create an Azure Resource Manager service connection for Azure deployments.

  • If you used Active Directory Federation Services (AD FS) as the identity provider for Azure Stack, you must create the service connection using a certificate rather than a client secret for authentication.

Set endpoint creation permissions

  1. In your Azure DevOps organization and project, select Project settings.

  2. Select Security, and under Azure DevOps Groups, select Endpoint Administrators.

  3. On the Members tab, select Add.

  4. In Add users and groups, select user names from the list, including yourself, and then select Save changes.

    Add a member

  5. In the Azure DevOps Groups list, select Endpoint Creators, and repeat the previous steps to add users to the Endpoint Creators group.

Create an endpoint for Azure AD or AD FS deployments

Follow the instructions in Create an Azure Resource Manager service connection with an existing service principal to create the service connection endpoint.

Use the following values to fill out the form:

  • Connection name: Enter a user-friendly name to use when referring to this service connection.

  • Environment: Select the environment name, such as AzureCloud or AzureStack. If you don't see AzureStack in the dropdown, see Connect to Azure Stack.

  • Environment URL: If you didn't select AzureCloud, enter your environment URL, such as https://management.local.azurestack.external.

  • Scope level: Select the scope level you need, such as Subscription.

  • Subscription ID: Enter your Subscription ID.

  • Subscription name: Enter your user name from Azure Stack.

  • Service principal client ID: Enter the Application (client) ID you saved previously.

  • Service principal key or Certificate: Select one or the other option.


    To create an AD FS endpoint, you must use a Certificate for authentication.

    • For Service principal key, enter the client secret value you saved earlier.

    • If you choose Certificate, enter the contents of both the certificate and private key sections of the .pem certificate file.


      To convert a .pfx to a .pem certificate file, run openssl pkcs12 -in file.pfx -out file.pem -nodes -password pass:<password_here>.

  • Tenant ID: Enter the Directory (tenant) ID you saved previously.

  • Connection: Not verified: Select Verify connection to validate your connection settings to the service principal.


    If your Azure Resource Manager endpoint isn't exposed to the internet, the connection validation will fail. This is expected, and you can validate your connection by creating a release pipeline with a simple task.

Install and configure the build agent

Using a hosted build agent in Azure Pipelines is a convenient option for building and deploying web apps. Azure automatically performs agent maintenance and upgrades, which enable a continuous and uninterrupted development cycle.

In Azure DevOps, create a personal access token (PAT) to use for Azure Stack. Then use the PAT to deploy and configure the build agent on the Azure Stack build server VM.

Create a personal access token

  1. Sign in to Azure DevOps and select My profile in the upper right corner.

  2. On your profile page, expand the dropdown next to your Azure Stack organization name, and select Manage security.

    Manage security

  3. On the Personal Access Tokens page, select New Token.

    Personal access tokens

  4. On the Create a new personal access token page, fill out the token information and select Create.

    Create a PAT

  5. Copy and save the token. It won't be shown again after you leave the web page.

    PAT warning

Install and configure the agent on the build server

  1. Connect to the build server VM you deployed on the Azure Stack host.

  2. Download the build agent image.

  3. In an administrator command prompt, deploy the agent as a service using your PAT, and run it.

  4. Navigate to the folder for the extracted build agent, and run the config.cmd file. The config.cmd updates the build agent folder with additional files.

    Install and configure the build agent

Now that you created the endpoint and installed the Azure Pipelines build agent on the build server, the Azure Pipelines to Azure Stack connection is ready to use. The build agent in Azure Stack gets instructions from Azure Pipelines, and then the agent conveys endpoint information for communication with Azure Stack.

‎‎Instead of managing each agent separately, you can organize agents into agent pools. An agent pool defines the sharing boundary for all agents in that pool. Agent pools are scoped to the Azure DevOps organization, which means that you can share an agent pool across projects. To learn more about agent pools, see Create agent pools and queues.

Create build and release pipelines

Azure Pipelines provides a highly configurable and manageable pipeline for releases to multiple environments such as development, staging, quality assurance (QA), and production. The release process can include requiring approvals at specific stages of the application life cycle.

In this part of the solution, you:

  • Clone, connect, and add code to your Azure DevOps project in Visual Studio.
  • Create a self-contained web app deployment.
  • Configure the CI/CD build and release pipelines.

Hybrid CI/CD can apply to both app code and infrastructure code. You can use Azure Resource Manager hybrid templates to deploy your Azure web app code to on-premises and public clouds.

Clone your project

  1. In Visual Studio Team Explorer, select the Connect icon and sign in to your Azure DevOps organization.

  2. Select Manage Connections > Connect to a project.

    Connect to a project from Team Explorer

  3. In the Connect to a Project dialog, select your web app project, set a local path, and then select Clone to clone the repository locally.

    Clone repository in Connect to a Project

Create a self-contained web app deployment for App Services in both clouds

  1. In Visual Studio Solution Explorer, open your WebApplication.csproj file and add <RuntimeIdentifier>win10-x64</RuntimeIdentifier>. For more information about this step, see Self-contained deployment.

    Configure RuntimeIdentifier

  2. Save your work, and use Team Explorer to check the code into your project.

Create a build pipeline and run a build

  1. In your web browser, open your Azure DevOps organization and project.

  2. Select Pipelines > Builds in the left navigation, and then select New pipeline.

  3. Select your code repository. Azure Pipelines analyzes and identifies your project as ASP.NET Core, and opens the default ASP.NET Core azure-pipelines.yml build template.

    ASP.NET Core azure-pipelines.yml file

  4. You can edit the pipeline code directly, or select Show assistant to open a Tasks pane that helps you add tasks and steps.

    If you select Show assistant, select .NET Core in the Tasks pane. In the .NET Core form:

    • Under Command, drop down and select publish.
    • Under Arguments, enter -r win10-x64.
    • Make sure Publish Web Projects is selected.
    • Select Add.

    Instead of using the assistant, you can edit and add the following code directly to the azure-pipelines.yml file:

    • Under pool, change the vmImage from ubuntu-latest to vs2017-win2016.

    • Under steps, add the DotNetCoreCLI task, command, and arguments:

      - task: DotNetCoreCLI@2
          command: 'publish'
          publishWebProjects: true
          arguments: '-r win10-x64'

    Your azure-pipelines.yml file should now have the following code:

    # ASP.NET Core
    # Build and test ASP.NET Core projects targeting .NET Core.
    # Add steps that run tests, create a NuGet package, deploy, and more:
    - master
      vmImage: 'vs2017-win2016'
      buildConfiguration: 'Release'
    - script: dotnet build --configuration $(buildConfiguration)
      displayName: 'dotnet build $(buildConfiguration)'
    - task: DotNetCoreCLI@2
        command: 'publish'
        publishWebProjects: true
        arguments: '-r win10-x64'
  5. Select Save and run, add a commit message and optional description, and select Save and run again.

The self-contained deployment build publishes artifacts that can run on both Azure and Azure Stack.

Create a release pipeline

Creating a release pipeline is the final step in your hybrid CI/CD configuration process. You use the release pipeline to create a release and deploy your build.

  1. In your Azure DevOps project, select Pipelines > Releases in the left navigation, and then select New pipeline.

  2. On the Select a template page, select Azure App Service deployment, and then select Apply.

    Select the release template

  3. On the Pipeline tab, select Add an artifact in the left pane. In the right pane, select the web app build you just created from the Source (build pipeline) drop-down menu, and select Add.

    Add a build artifact

  4. On the Pipeline tab, under Stages, select the hyperlink in Stage 1 to View stage tasks.

    View stage tasks

  5. On the Tasks tab, enter Azure as the Stage name.

  6. Under Parameters, select your subscription from the Azure subscription drop-down list, and enter your App service name.

    Select subscription and enter App Service name

  7. In the left pane, select Run on agent. In the right pane, select Azure Pipelines from the Agent pool drop-down list, and then select vs2017-win2016 from the Agent Specification drop-down list.

    Select hosted agent

  8. In the left pane, select Deploy Azure App Service. In the right pane, scroll down and select the ellipsis ... next to Package or folder.

    Select package or folder

  9. In the Select a file or folder dialog, browse to the location of your Azure web app build, and then select OK.

  10. On the New release pipeline page, select Save at upper right.

  11. On the Pipeline tab, select Add an artifact. Select your project, and then select your Azure Stack build from the Source (build pipeline) drop-down menu. Select Add.

  12. Under Stages, hover over the Azure stage until the + appears, and then select Add.

  13. Under Template, select Empty job.

  14. In the Stage dialog, enter Azure Stack as the stage name.

    View new stage

  15. Under Parameters, select your Azure Stack endpoint, and enter your Azure Stack web app name as the App service name.

  16. Under Run on agent, select your Azure Stack build server agent from the Agent pool drop-down list.

  17. For Deploy Azure App Service, select the Package or folder for the Azure Stack build, and then select OK in the Select a file or folder dialog.

  18. On the Variables tab, find the variable named VSTS_ARM_REST_IGNORE_SSL_ERRORS. Set the variable value to true, and set its scope to Azure Stack.

    Configure variable

  19. On the Pipeline tab, select the Continuous deployment trigger icon for each artifact, and set it to Enabled.

    Set continuous deployment trigger

  20. Select the Pre-deployment conditions icon on the Azure Stack stage, and set the trigger to After release.

    Set pre-deployment conditions trigger

  21. Select Save at the upper right on the New release pipeline page to save the release pipeline.


Some settings for release tasks may have been automatically defined as custom variables when you created the release pipeline from the template. These settings can't be modified in the task settings, but you can edit them in the parent stage items.

Release the app

Now that you have a release pipeline, you can use it to create a release and deploy your app.

Because the continuous deployment trigger is set in your release pipeline, modifying the source code starts a new build and creates a new release automatically. However, this time you'll create and run a new release manually.

To create and deploy a release:

  1. On your new release pipeline page, select Create release at upper right.

    Create a release

  2. On the Create a new release page:

    1. Under Pipeline, select the Azure stage to change its trigger from automated to manual.
    2. Under Artifacts, make sure the correct artifacts are selected.
    3. Enter a Release description, and then select Create.

    A banner indicates that the new release is created. You can select the release name link to see a release summary page showing details about the release, such as deployment status.

  3. To deploy the manual release, select the Azure stage, select Deploy, and then select Deploy in the stage dialog.

  4. When the deployment completes successfully, open the deployed app in your browser. For example, for the Azure App Services website, open the URL https://<your-app-name>

Monitor and track releases

You can select the hyperlinked status in a release stage to see more information about the deployment.

Release summary page

It's easy for an administrator to track the overall progress of releases, and see which releases are waiting for approval.

Release summary page showing pending approval

You can see the release logs from all your deployments:

  1. In your Azure DevOps project, Select Pipelines > Releases on the left, and then select a release.

  2. On the release summary page, hover over or select a stage, and then select Logs.

    In the release log, the left pane shows the status of each operation for each stage. During a deployment, the right pane shows the live log from the agent. After the deployment finishes, the entire log file appears in the right pane.

  3. Select any step in the left pane to see the log file for that step, such as Pre-deployment approvals.

  4. To view approvals, select View approval in the right pane to see who approved or rejected the release, and other details.

Seeing logs for the individual steps makes it easier to trace and debug parts of the overall deployment. You can also Download all logs as a .zip file.

Release log

Next steps

To learn more about Azure Cloud Patterns, see Cloud Design Patterns.