Servers - IIS - Advanced configuration

In this article

This article covers advanced configuration options and scenarios for the ASP.NET Core Module and IIS.

Modify the stack size

Only applies when using the in-process hosting model.

Configure the managed stack size using the stackSize setting in bytes in the web.config file. The default size is 1,048,576 bytes (1 MB). The following example changes the stack size to 2 MB (2,097,152 bytes):

<aspNetCore processPath="dotnet"
    arguments=".\MyApp.dll"
    stdoutLogEnabled="false"
    stdoutLogFile="\\?\%home%\LogFiles\stdout"
    hostingModel="inprocess">
  <handlerSettings>
    <handlerSetting name="stackSize" value="2097152" />
  </handlerSettings>
</aspNetCore>

Disallow rotation on config

The disallowRotationOnConfigChange setting is intended for blue/green scenarios where a change to global config should not cause all sites to recycle. When this flag is true, only changes relevant to the site itself will cause it to recycle. For example, a site recycles if its web.config changes or something changes that is relevant to the site's path from IIS's perspective. But a general change to applicationHost.config would not cause an app to recycle. The following example sets this setting to true:

<aspNetCore processPath="dotnet"
    arguments=".\MyApp.dll"
    stdoutLogEnabled="false"
    stdoutLogFile="\\?\%home%\LogFiles\stdout"
    hostingModel="inprocess">
  <handlerSettings>
    <handlerSetting name="disallowRotationOnConfigChange" value="true" />
  </handlerSettings>
</aspNetCore>

This setting corresponds to the API ApplicationPoolRecycling.DisallowRotationOnConfigChange

Reduce 503 likelihood during app recycle

By default, there is a one second delay between when IIS is notified of a recycle or shutdown and when ANCM tells the managed server to initiate shutdown. The delay is configurable via the ANCM_shutdownDelay environment variable or by setting the shutdownDelay handler setting. Both values are in milliseconds. The delay is primarily to reduce the likelihood of a race where:

This setting doesn't mean incoming requests will be delayed by this amount. The setting indicates that the old app instance will start shutting down after the timeout occurs. Slower machines or machines with heavier CPU usage might need to adjust this value to reduce 503 likelihood.

The following example sets the delay to 5 seconds:

<aspNetCore processPath="dotnet"
    arguments=".\MyApp.dll"
    stdoutLogEnabled="false"
    stdoutLogFile="\\?\%home%\LogFiles\stdout"
    hostingModel="inprocess">
  <handlerSettings>
    <handlerSetting name="shutdownDelay" value="5000" />
  </handlerSettings>
</aspNetCore>

Proxy configuration uses HTTP protocol and a pairing token

Only applies to out-of-process hosting.

The proxy created between the ASP.NET Core Module and Kestrel uses the HTTP protocol. There's no risk of eavesdropping the traffic between the module and Kestrel from a location off of the server.

A pairing token is used to guarantee that the requests received by Kestrel were proxied by IIS and didn't come from some other source. The pairing token is created and set into an environment variable (ASPNETCORE_TOKEN) by the module. The pairing token is also set into a header (MS-ASPNETCORE-TOKEN) on every proxied request. IIS Middleware checks each request it receives to confirm that the pairing token header value matches the environment variable value. If the token values are mismatched, the request is logged and rejected. The pairing token environment variable and the traffic between the module and Kestrel aren't accessible from a location off of the server. Without knowing the pairing token value, an attacker can't submit requests that bypass the check in the IIS Middleware.

ASP.NET Core Module with an IIS Shared Configuration

The ASP.NET Core Module installer runs with the privileges of the TrustedInstaller account. Because the local system account doesn't have modify permission for the share path used by the IIS Shared Configuration, the installer throws an access denied error when attempting to configure the module settings in the applicationHost.config file on the share.

When using an IIS Shared Configuration on the same machine as the IIS installation, run the ASP.NET Core Hosting Bundle installer with the OPT_NO_SHARED_CONFIG_CHECK parameter set to 1:

dotnet-hosting-{VERSION}.exe OPT_NO_SHARED_CONFIG_CHECK=1

When the path to the shared configuration isn't on the same machine as the IIS installation, follow these steps:

Data protection

The ASP.NET Core Data Protection stack is used by several ASP.NET Cores, including used in authentication.

If the Data Protection key ring is stored in memory when the app restarts:

To configure data protection under IIS to persist the key ring, use one of the following approaches:

Navigate to the %windir%/system32/inetsrv/config folder. Open the applicationHost.config file. Locate the <system.applicationHost> element. Confirm that the setProfileEnvironment attribute isn't present, which defaults the value to true, or explicitly set the attribute's value to true.

IIS configuration

Windows Server operating systems

Enable the Web Server (IIS) server role and establish role services.

The Web Server IIS role is selected in the Select server roles step.!

Windows Authentication (Optional) To enable Windows Authentication, expand the following nodes: Web Server > Security. Select the Windows Authentication feature. For more information, see Windows Authentication and Configure Windows authentication. WebSockets (Optional) WebSockets is supported with ASP.NET Core 1.1 or later. To enable WebSockets, expand the following nodes: Web Server > Application Development. Select the WebSocket Protocol feature. For more information, see WebSockets.

The default role services are selected in the Select role services step.!

Windows desktop operating systems

Enable the IIS Management Console and World Wide Web Services.

IIS Management Console and World Wide Web Services are selected in Windows Features.!

Virtual Directories

IIS Virtual Directories aren't supported with ASP.NET Core apps. An app can be hosted as a sub-application.

Sub-applications

An ASP.NET Core app can be hosted as an IIS sub-application (sub-app). The sub-app's path becomes part of the root app's URL.

Static asset links within the sub-app should use tilde-slash (/) notation in MVC and Razor Pages. Tilde-slash notation triggers a Tag Helper to prepend the sub-app's pathbase to the rendered relative link. For a sub-app at /subapp_path, an image linked with src="/image.png" is rendered as src="/subapp_path/image.png". The root app's Static File Middleware doesn't process the static file request. The request is processed by the sub-app's Static File Middleware.

Note Razor components (.razor) shouldn't use tilde-slash notation. For more information, see the Blazor app base path documentation.

If a static asset's src attribute is set to an absolute path (for example, src="/image.png"), the link is rendered without the sub-app's pathbase. The root app's Static File Middleware attempts to serve the asset from the root app's web root, which results in a 404 - Not Found response unless the static asset is available from the root app.

To host an ASP.NET Core app as a sub-app under another ASP.NET Core app:

The assignment of a separate app pool to the sub-app is a requirement when using the in-process hosting model.

For more information on the in-process hosting model and configuring the ASP.NET Core Module, see ASP.NET Core Module (ANCM) for IIS.

Application Pools

App pool isolation is determined by the hosting model:

When a website is added to an app pool, a new app pool is created using the site name when the site is added.

Application Pool Identity

An app pool identity account allows an app to run under a unique account without having to create and manage domains or local accounts. On IIS 8.0 or later, the IIS Admin Worker Process (WAS) creates a virtual account with the name of the new app pool and runs the app pool's worker processes under this account by default. In the IIS Management Console under Advanced Settings for the app pool, ensure that the Identity is set to use ApplicationPoolIdentity:

Application pool advanced settings dialog!

An app pool can be managed using the Windows User Management Console.

If the IIS worker process requires elevated access to the app, modify the Access Control List (ACL) for the directory containing the app:

![Select users or groups dialog for the app folder: The app pool name of "DefaultAppPool" is appended to "IIS AppPool" in the object names area before selecting "Check Names."!](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/index/_static/select-users-or-groups-1.png?view=aspnetcore-8.0 "Select users or groups dialog for the app folder: The app pool name of "DefaultAppPool" is appended to "IIS AppPool" in the object names area before selecting "Check Names."")

![Select users or groups dialog for the app folder: After selecting "Check Names," the object name "DefaultAppPool" is shown in the object names area.!](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/index/_static/select-users-or-groups-2.png?view=aspnetcore-8.0 "Select users or groups dialog for the app folder: After selecting "Check Names," the object name "DefaultAppPool" is shown in the object names area.")

Access can also be granted at a command prompt using the ICACLS tool. Using the DefaultAppPool as an example, the following command is used to grant read and execute permissions to the MyWebApp folder, subfolders, and files:

ICACLS C:\sites\MyWebApp /grant "IIS AppPool\DefaultAppPool:(OI)(CI)RX"

For more information, see the icacls topic.

HTTP/2 support

HTTP/2 is supported with ASP.NET Core in the following IIS deployment scenarios:

For an in-process deployment when an HTTP/2 connection is established, HttpRequest.Protocol reports HTTP/2. For an out-of-process deployment when an HTTP/2 connection is established, HttpRequest.Protocol reports HTTP/1.1.

For more information on the in-process and out-of-process hosting models, see ASP.NET Core Module (ANCM) for IIS.

HTTP/2 is enabled by default. Connections fall back to HTTP/1.1 if an HTTP/2 connection isn't established. For more information on HTTP/2 configuration with IIS deployments, see HTTP/2 on IIS.

CORS preflight requests

This section only applies to ASP.NET Core apps that target the .NET Framework.

For an ASP.NET Core app that targets the .NET Framework, OPTIONS requests aren't passed to the app by default in IIS. To learn how to configure the app's IIS handlers in web.config to pass OPTIONS requests, see Enable cross-origin requests in ASP.NET Web API 2: How CORS Works.

Application Initialization Module and Idle Timeout

When hosted in IIS by the ASP.NET Core Module version 2:

Application Initialization Module

Applies to apps hosted in-process and out-of-process.

IIS Application Initialization is an IIS feature that sends an HTTP request to the app when the app pool starts or is recycled. The request triggers the app to start. By default, IIS issues a request to the app's root URL (/) to initialize the app (see the additional resources for more details on configuration).

Confirm that the IIS Application Initialization role feature in enabled:

On Windows 7 or later desktop systems when using IIS locally:

On Windows Server 2008 R2 or later:

Use either of the following approaches to enable the Application Initialization Module for the site:

Select Application Pools in the Connections panel. Right-click the app's app pool in the list and select Advanced Settings. The default Start Mode is OnDemand. Set the Start Mode to AlwaysRunning. Select OK. Open the Sites node in the Connections panel. Right-click the app and select Manage Website > Advanced Settings. The default Preload Enabled setting is False. Set Preload Enabled to True. Select OK.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <applicationInitialization doAppInitAfterRestart="true" />
    </system.webServer>
  </location>
</configuration>

Idle Timeout

Only applies to apps hosted in-process.

To prevent the app from idling, set the app pool's idle timeout using IIS Manager:

To prevent apps hosted out-of-process from timing out, use either of the following approaches:

Application Initialization Module and Idle Timeout additional resources

Module, schema, and configuration file locations

Module

IIS (x86/amd64):

IIS Express (x86/amd64):

Schema

IIS

IIS Express

Configuration

IIS

IIS Express

The files can be found by searching for aspnetcore in the applicationHost.config file.

Install Web Deploy when publishing with Visual Studio

When deploying apps to servers with Web Deploy, install the latest version of Web Deploy on the server. To install Web Deploy, see IIS Downloads: Web Deploy.

Create the IIS site

Warning Top-level wildcard bindings (http://*:80/ and http://+:80) should not be used. Top-level wildcard bindings can open up your app to security vulnerabilities. This applies to both strong and weak wildcards. Use explicit host names rather than wildcards. Subdomain wildcard binding (for example, *.mysub.com) doesn't have this security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable). See RFC 9110: HTTP Semantics (Section 7.2: Host and :authority) for more information.

Supply the Site name, physical path, and Host name in the Add Website step.!

Warning Top-level wildcard bindings (http://*:80/ and http://+:80) should not be used. Top-level wildcard bindings can open up your app to security vulnerabilities. This applies to both strong and weak wildcards. Use explicit host names rather than wildcards. Subdomain wildcard binding (for example, *.mysub.com) doesn't have this security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable). See RFC 9110: HTTP Semantics (Section 7.2: Host and :authority) for more information.

ASP.NET Core runs in a separate process and manages the runtime. ASP.NET Core doesn't rely on loading the desktop CLR (.NET CLR). The Core Common Language Runtime (CoreCLR) for .NET Core is booted to host the app in the worker process. Setting the .NET CLR version to No Managed Code is optional but recommended.

Set No Managed Code for the .NET CLR version.!

Windows Authentication configuration (Optional) For more information, see Configure Windows authentication.

Shadow copy

Ref: Advanced configuration of the ASP.NET Core Module and IIS