Introduction to Web Deploy on Windows Server 2022
Web Deploy (msdeploy.exe) is Microsoft’s deployment tool for synchronizing web applications, databases, and server configurations between machines. It integrates with IIS, Visual Studio, and CI/CD pipelines to enable one-command deployments that transfer only changed files, transform configuration, and execute pre/post-deployment scripts. This guide covers every component from service installation to pipeline integration and troubleshooting.
Installing Web Deploy on IIS Server
Web Deploy is installed separately from IIS. Download the Web Deploy 4.0 MSI from the Microsoft IIS Downloads page at https://www.iis.net/downloads/microsoft/web-deploy. Run the installer and choose Complete installation to include all components including the agent service. Alternatively install via PowerShell using the WebPI command-line tool or Chocolatey:
choco install webdeploy -y
Verify the installation path and version:
& "C:Program FilesIISMicrosoft Web Deploy V3msdeploy.exe" -version
After installation you will see two new Windows services:
Get-Service WMSVC # IIS Management Service (port 8172)
Get-Service MsDepSvc # Web Deployment Agent Service (port 80/443)
IIS Management Service Configuration
The IIS Management Service (WMSVC) must be running on the target server and configured to allow remote connections. Open IIS Manager on the server, navigate to the server node, and double-click Management Service. Enable remote connections and configure the binding:
# Enable IIS Management Service via PowerShell
Set-ItemProperty "HKLM:SOFTWAREMicrosoftWebManagementServer" -Name "EnableRemoteManagement" -Value 1
Start-Service WMSVC
Set-Service WMSVC -StartupType Automatic
Open the firewall port for the Management Service (default 8172):
New-NetFirewallRule -DisplayName "IIS Management Service" -Direction Inbound `
-Protocol TCP -LocalPort 8172 -Action Allow
Web Deployment Agent Service
The Web Deployment Agent Service (MsDepSvc) provides an alternative endpoint for Web Deploy operations on port 80. It runs as Local System and handles deployments authenticated with Windows credentials. This service is typically used in domain environments where the deploying user has local administrator rights on the target server.
Start-Service MsDepSvc
Set-Service MsDepSvc -StartupType Automatic
The agent endpoint URL follows this pattern:
http://targetserver/msdeployagentservice
Configuring Web Deploy Permissions
For non-administrator deployments, create a dedicated IIS user and grant it permissions. This is the recommended approach for build server deployments where you do not want to use domain admin credentials. In IIS Manager, navigate to Management Service Delegation under the server node. Add rules for the deployment user to allow the iisApp, contentPath, and setAcl providers.
# Create a local IIS management user
New-LocalUser -Name "DeployUser" -Password (ConvertTo-SecureString "D3pl0y@Pass" -AsPlainText -Force)
# Add to IIS_IUSRS group
Add-LocalGroupMember -Group "IIS_IUSRS" -Member "DeployUser"
# Grant write access to the site content directory
icacls "C:inetpubwwwrootMyApp" /grant "DeployUser:(OI)(CI)M"
Create the delegation rules programmatically using the appcmd.exe tool:
%windir%system32inetsrvappcmd.exe set config -section:management/delegation `
/+"[path='Default Web Site/MyApp',username='DeployUser',password='D3pl0y@Pass',`
allowed='true',providers='iisApp,contentPath,setAcl,recycleApp']"
Deploying from Visual Studio
In Visual Studio right-click the project and select Publish. Choose Web Server (IIS) then Web Deploy. Configure the publish profile:
Server: targetserver:8172
Site name: Default Web Site/MyApp
User name: DeployUser
Password: D3pl0y@Pass
Destination URL: http://targetserver/MyApp
The publish profile is saved as a .pubxml file in PropertiesPublishProfiles within the project. This file can be committed to source control (credentials should use environment variable references):
MSDeploy
targetserver:8172
Default Web Site/MyApp
DeployUser
False
True
Deploying from the Command Line with msdeploy.exe
The msdeploy.exe command-line tool gives full control over deployments. The basic sync operation copies a local directory to a remote IIS application:
"C:Program FilesIISMicrosoft Web Deploy V3msdeploy.exe" `
-verb:sync `
-source:contentPath="C:buildMyApppublish" `
-dest:iisApp="Default Web Site/MyApp",`
computername="https://targetserver:8172/msdeploy.axd",`
userName="DeployUser",`
password="D3pl0y@Pass",`
authtype="Basic" `
-allowUntrusted `
-enableRule:AppOffline
The -enableRule:AppOffline flag drops an App_Offline.htm file before deployment so IIS takes the app offline gracefully, then removes it after sync completes. To deploy only specific changed files and skip configuration files:
"C:Program FilesIISMicrosoft Web Deploy V3msdeploy.exe" `
-verb:sync `
-source:contentPath="C:buildMyApppublish" `
-dest:iisApp="Default Web Site/MyApp",computername="https://targetserver:8172/msdeploy.axd",userName="DeployUser",password="D3pl0y@Pass",authtype="Basic" `
-skip:objectName=filePath,absolutePath="web.config$" `
-enableRule:DoNotDeleteRule `
-allowUntrusted
Delta Sync — Deploying Only Changed Files
Web Deploy automatically computes a delta and transfers only files that differ. This is built into the sync verb and requires no special configuration. You can observe what would be transferred without actually deploying by using the -whatif flag:
"C:Program FilesIISMicrosoft Web Deploy V3msdeploy.exe" `
-verb:sync `
-source:contentPath="C:buildMyApppublish" `
-dest:iisApp="Default Web Site/MyApp",computername="https://targetserver:8172/msdeploy.axd",userName="DeployUser",password="D3pl0y@Pass",authtype="Basic" `
-whatif `
-allowUntrusted
The output lists each file action: Add, Delete, Update. Web Deploy compares file hashes and modification dates to determine what needs transferring.
Web.config Transformations
Config transforms allow environment-specific settings. Add a transform file named web.Release.config to your project. Example that replaces the connection string and removes debug mode:
During publish, MSBuild applies the transform before Web Deploy packages the application. Run the transform manually:
dotnet publish -c Release -o C:buildMyApppublish
Deploying ASP.NET Core Apps
For ASP.NET Core, publish the app self-contained or as framework-dependent, then deploy the publish output. Enable the ASP.NET Core Module (ANCM) in IIS:
# Install the ASP.NET Core Hosting Bundle on the target server
# Download from https://dotnet.microsoft.com/download
# Run the installer, then restart IIS
iisreset /restart
Configure the IIS site to use a No Managed Code application pool:
New-WebAppPool -Name "MyAppPool"
Set-ItemProperty "IIS:AppPoolsMyAppPool" -Name managedRuntimeVersion -Value ""
New-Website -Name "MyApp" -PhysicalPath "C:inetpubwwwrootMyApp" `
-ApplicationPool "MyAppPool" -Port 80
Deploying from Azure DevOps
Add a Web Deploy step to your Azure DevOps pipeline using the IIS Web App Deploy task. In your azure-pipelines.yml:
- task: IISWebAppDeploymentOnMachineGroup@0
displayName: 'Deploy to IIS'
inputs:
WebSiteName: 'Default Web Site/MyApp'
Package: '$(Pipeline.Workspace)/drop/MyApp.zip'
TakeAppOfflineFlag: true
XmlTransformation: true
XmlVariableSubstitution: true
This task runs on a deployment group agent installed on the target server. Install the agent on the server by navigating to Project Settings > Deployment groups in Azure DevOps and running the provided registration script.
Deploying from GitHub Actions
GitHub Actions can deploy to IIS via Web Deploy using the self-hosted runner or via direct msdeploy.exe invocation:
name: Deploy to IIS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: dotnet publish -c Release -o ./publish
- name: Deploy via Web Deploy
run: |
& "C:Program FilesIISMicrosoft Web Deploy V3msdeploy.exe" `
-verb:sync `
-source:contentPath="${{ github.workspace }}publish" `
-dest:iisApp="Default Web Site/MyApp",computername="https://${{ secrets.SERVER_HOST }}:8172/msdeploy.axd",userName="${{ secrets.DEPLOY_USER }}",password="${{ secrets.DEPLOY_PASS }}",authtype="Basic" `
-allowUntrusted `
-enableRule:AppOffline
Store SERVER_HOST, DEPLOY_USER, and DEPLOY_PASS as GitHub Actions secrets. Never hardcode credentials in workflow files.
Troubleshooting Web Deploy Connectivity
Common Web Deploy errors and resolutions:
Error: Could not connect to the remote computer — Verify the Management Service is running, port 8172 is open in Windows Firewall, and the service URL is correct. Test connectivity:
Test-NetConnection -ComputerName targetserver -Port 8172
Error: A specified logon session does not exist — The Management Service may not have the delegation rule for the user. Re-check the Management Service Delegation configuration in IIS Manager.
Error: Web deployment task failed. (The site does not exist) — The site name in the destination must exactly match the IIS site and application path. List sites to verify:
Get-Website | Select Name, PhysicalPath, State
Get-WebApplication | Select Site, Path, PhysicalPath
Certificate validation errors with -allowUntrusted — In production, install a valid TLS certificate for the Management Service. In IIS Manager, select the server node, open Management Service, and change the SSL certificate to your trusted cert, then restart WMSVC.
Verbose logging — Add -verbose to the msdeploy command line for detailed operation-by-operation output that identifies exactly which files are failing and why:
"C:Program FilesIISMicrosoft Web Deploy V3msdeploy.exe" -verb:sync ... -verbose 2>&1 | Tee-Object -FilePath C:logsdeploy.log
Summary
Web Deploy on Windows Server 2022 provides a robust, delta-aware deployment mechanism for IIS-hosted applications. By configuring dedicated deployment users with minimal required permissions, leveraging config transforms for environment promotion, and integrating with Azure DevOps or GitHub Actions, teams can achieve repeatable, automated deployments that minimize downtime. The combination of the Management Service for non-administrator deployments, AppOffline rules for graceful shutdowns, and verbose logging for diagnostics covers the full deployment lifecycle for enterprise ASP.NET applications.