Remigiusz ZalewskiRemigiusz Zalewski

How to Set Up a Release Pipeline for ASP.NET Core in Azure DevOps

how-to-set-up-a-release-pipeline-for-aspnet-core-in-azure-devops

Introduction

At some point, manually deploying your ASP.NET Core app to a server gets old fast. You merge to main, then you open Azure DevOps, kick off a release, RDP into the VM, check the logs - it's a lot of overhead that compounds with every deploy.

The fix is a proper CD pipeline. Once it's wired up, every successful CI build triggers a deployment automatically. Your code goes from a merge to a live site without you lifting a finger.

In this article, you'll see the full setup: provisioning an Azure VM, enabling IIS, installing the .NET Hosting Bundle, connecting the VM to Azure DevOps via a Deployment Group, and building the Release Pipeline itself with an IIS Web App Deploy task.

🎬 Watch the full video here:


⚙️ Provisioning the Azure Virtual Machine

If you already have a VM running Windows Server with IIS, skip this section and jump straight to the Deployment Group setup.

For everyone starting fresh: in the Azure Portal, create a new Virtual Machine with these settings:

  • OS: Windows Server 2025 Datacenter Gen 2
  • Inbound ports: HTTP and HTTPS only
  • RDP: do not open to all IPs - lock it down after creation

On RDP specifically - once the VM is created, go to the Network Security Group and add an inbound rule that allows RDP only from your own public IP. If you leave RDP open to the world and your credentials ever leak, the machine is exposed. Check your current IP at whatismyip.com, then create the rule with that IP as the source.


🌐 Enabling IIS and Installing the .NET Hosting Bundle

Connect to the VM via RDP and do two things before touching Azure DevOps.

Enable IIS

Open Server Manager, go to Manage - Add Roles and Features, and enable the Web Server (IIS) role. Once installed, open IIS Manager from the Tools menu - you should see a Default Web Site already present.

Install the .NET Hosting Bundle

Your ASP.NET Core app needs the Hosting Bundle installed on the server - not just the runtime. Open a command prompt and run:

dotnet --list-runtimes

If you get "command not found" or an empty list, the bundle is not installed. Download the correct version from the official .NET download page (in this case .NET 10) and select the Hosting Bundle option - not the SDK or the runtime alone.

After installation, restart the VM and verify:

dotnet --list-runtimes

You should now see the installed runtime. In IIS Manager, go to the server node - Modules, and confirm that AspNetCoreModuleV2 is listed. That module is what allows IIS to host ASP.NET Core apps as a reverse proxy.

Key points:

  • Always install the Hosting Bundle, not just the runtime
  • The ASP.NET Core Module V2 must appear in IIS Modules before any deployment
  • Match the bundle version to the target framework of your application

🔗 Connecting the VM to Azure DevOps via a Deployment Group

A Deployment Group is how Azure DevOps establishes a trusted connection to your server. Once registered, the VM appears as a deployment target inside your release pipeline.

In Azure DevOps, go to Pipelines - Deployment Groups and click Add a deployment group. Give it a name - for example ProductionDeploymentGroup.

Azure DevOps will generate a PowerShell registration script. Check the option to use a Personal Access Token for authentication, then copy the script.

On the VM, open PowerShell as Administrator, paste the script, and press Enter through the default prompts. When the script completes, go back to the Deployment Groups page in Azure DevOps and refresh - you should see your VM listed with a status of Online and Healthy.

Key points:

  • Run the registration script with admin privileges
  • The agent installed by the script runs as a Windows service on the VM
  • One Deployment Group can hold multiple VMs for multi-server deployments

🚀 Building the Release Pipeline

Go to Pipelines - Releases - New Pipeline. You will configure two things: the artifact source and the deployment stage.

Artifact Source

Click Add an artifact and select your CI build pipeline as the source. Enable the Continuous Deployment trigger (the lightning bolt icon). This is what makes every successful CI build automatically kick off a new release - no manual intervention needed.

Deployment Stage

Add a stage and select the IIS Website Deployment template. Rename the stage to something like Deploy to IIS Server for clarity.

Click into the stage tasks. You will configure three tasks:

Deployment process

Set up the binding for your ASP.NET Core application. In this example, port 81 with HTTP. Choose your desired website name.

IIS Deployment

  • Set the Deployment Group to ProductionDeploymentGroup
  • Enable Allow scripts to access the OAuth token

IIS Web App Manage

Configure the website and app pool that Azure DevOps will create or update on the VM:

  • Website name: TaskManager (or your app name) - automatically fetched from the previous step
  • Physical path: a dedicated folder on the VM, e.g. %SystemDrive%\inetpub\wwwroot\TaskManager
  • Physical path authentication: Application User
  • Binding port: automatically fetched from the first step
  • App pool name: TaskManager
  • .NET CLR version: No Managed Code (required for ASP.NET Core)
  • Identity: Custom Account - use pipeline variables for credentials (see below)

IIS Web App Deploy

Leave the Package or Folder field pointing to the artifact zip from your CI pipeline. Azure DevOps populates this automatically when you selected the artifact source.

Pipeline Variables

Instead of hardcoding VM credentials, use pipeline variables. Go to the Variables tab and add:

  • username - your VM admin username
  • password - your VM admin password (mark as secret)

Reference them in the app pool identity fields as $(username) and $(password).


Running Your First Release

Save the pipeline as CD-[YourAppName] and click Create a Release. Watch the logs - each task should complete with a green tick.

Once the pipeline finishes, open IIS Manager on the VM. Your site should appear alongside the Default Web Site. Click Browse and confirm the application loads. If you have a Swagger or Scalar endpoint, navigate to /swagger or /scalar to verify the API is responding correctly.

From this point forward, every push that triggers your CI build will also trigger this release pipeline and deploy the latest version automatically.


Key Takeaways

  • Register your VM with Azure DevOps via a Deployment Group before building any release pipeline - it is the foundation of the connection.
  • Always install the .NET Hosting Bundle on the IIS server, not just the runtime, and verify that AspNetCoreModuleV2 is present in IIS Modules.
  • Lock RDP access to your specific IP in the Network Security Group - never leave it open to all addresses.
  • Use pipeline variables for VM credentials instead of hardcoding them in the pipeline configuration.
  • Enable the Continuous Deployment trigger on your artifact source to achieve true CD - zero manual steps from code push to live deployment.

Resources