By [Luke Latham](https://github.com/guardrex) and [Rick Anderson](https://twitter.com/RickAndMSFT)
## Supported operating systems
The following operating systems are supported:
* Windows 7 and newer
* Windows Server 2008 R2 and newer†
†Conceptually, the IIS configuration described in this document also applies to hosting ASP.NET Core apps on Nano Server IIS, but refer to [ASP.NET Core with IIS on Nano Server](xref:tutorials/nano-server) for specific instructions.
[HTTP.sys server](xref:fundamentals/servers/httpsys) (formerly called [WebListener](xref:fundamentals/servers/weblistener)) won't work in a reverse proxy configuration with IIS. Use the [Kestrel server](xref:fundamentals/servers/kestrel).
## IIS configuration
Enable the **Web Server (IIS)** role and establish role services.
### Windows desktop operating systems
Navigate to **Control Panel** > **Programs** > **Programs and Features** > **Turn Windows features on or off** (left side of the screen). Open the group for **Internet Information Services** and **Web Management Tools**. Check the box for **IIS Management Console**. Check the box for **World Wide Web Services**. Accept the default features for **World Wide Web Services** or customize the IIS features.
![IIS Management Console and World Wide Web Services are selected in Windows Features.](index/_static/windows-features-win10.png)
### Windows Server operating systems
For server operating systems, use the **Add Roles and Features** wizard via the **Manage** menu or the link in **Server Manager**. On the **Server Roles** step, check the box for **Web Server (IIS)**.
![The Web Server IIS role is selected in the Select server roles step.](index/_static/server-roles-ws2016.png)
On the **Role services** step, select the IIS role services desired or accept the default role services provided.
![The default role services are selected in the Select role services step.](index/_static/role-services-ws2016.png)
Proceed through the **Confirmation** step to install the web server role and services. A server/IIS restart isn't required after installing the Web Server (IIS) role.
## Install the .NET Core Windows Server Hosting bundle
1. Install the [.NET Core Windows Server Hosting bundle](https://aka.ms/dotnetcore-2-windowshosting) on the hosting system. The bundle installs the .NET Core Runtime, .NET Core Library, and the [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module). The module creates the reverse proxy between IIS and the Kestrel server. If the system doesn't have an Internet connection, obtain and install the [Microsoft Visual C++ 2015 Redistributable](https://www.microsoft.com/download/details.aspx?id=53840) before installing the .NET Core Windows Server Hosting bundle.
2. Restart the system or execute **net stop was /y** followed by **net start w3svc** from a command prompt to pick up a change to the system PATH.
> [!NOTE]
> For information on IIS Shared Configuration, see [ASP.NET Core Module with IIS Shared Configuration](xref:host-and-deploy/aspnet-core-module#aspnet-core-module-with-an-iis-shared-configuration).
## Install Web Deploy when publishing with Visual Studio
When deploying apps to servers with [Web Deploy](/iis/publish/using-web-deploy/introduction-to-web-deploy), install the latest version of Web Deploy on the server. To install Web Deploy, use the [Web Platform Installer (WebPI)](https://www.microsoft.com/web/downloads/platform.aspx) or obtain an installer directly from the [Microsoft Download Center](https://www.microsoft.com/download/details.aspx?id=43717). The preferred method is to use WebPI. WebPI offers a standalone setup and a configuration for hosting providers.
## Application configuration
### Enabling the IISIntegration components
# [ASP.NET Core 2.x](#tab/aspnetcore2x)
A typical *Program.cs* calls [CreateDefaultBuilder](/dotnet/api/microsoft.aspnetcore.webhost.createdefaultbuilder) to begin setting up a host. `CreateDefaultBuilder` configures [Kestrel](xref:fundamentals/servers/kestrel) as the web server and enables IIS integration by configuring the base path and port for the [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module):
```csharp
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
...
```
# [ASP.NET Core 1.x](#tab/aspnetcore1x)
Include a dependency on the [Microsoft.AspNetCore.Server.IISIntegration](https://www.nuget.org/packages/Microsoft.AspNetCore.Server.IISIntegration/) package in the app's dependencies. Incorporate IIS Integration middleware into the app by adding the *UseIISIntegration* extension method to *WebHostBuilder*:
```csharp
var host = new WebHostBuilder()
.UseKestrel()
.UseIISIntegration()
...
```
Both `UseKestrel` and `UseIISIntegration` are required. Code calling `UseIISIntegration` doesn't affect code portability. If the app isn't run behind IIS (for example, the app is run directly on Kestrel), `UseIISIntegration` no-ops.
---
For more information on hosting, see [Hosting in ASP.NET Core](xref:fundamentals/hosting).
### IIS options
To configure IIS options, include a service configuration for `IISOptions` in `ConfigureServices`:
| `AutomaticAuthentication` | `true` | If `true`, the authentication middleware sets the `HttpContext.User` and responds to generic challenges. If `false`, the authentication middleware only provides an identity (`HttpContext.User`) and responds to challenges when explicitly requested by the `AuthenticationScheme`. Windows Authentication must be enabled in IIS for `AutomaticAuthentication` to function. |
| `AuthenticationDisplayName` | `null` | Sets the display name shown to users on login pages. |
| `ForwardClientCertificate` | `true` | If `true` and the `MS-ASPNETCORE-CLIENTCERT` request header is present, the `HttpContext.Connection.ClientCertificate` is populated. |
### web.config
The *web.config* file's primary purpose is to configure the [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module). It may optionally provide additional IIS configuration settings. Creating, transforming, and publishing *web.config* is handled by the .NET Core Web SDK (`Microsoft.NET.Sdk.Web`). The SDK is set at the top of the project file, `<Project Sdk="Microsoft.NET.Sdk.Web">`. To prevent the SDK from transforming the *web.config* file, add the **\<IsTransformWebConfigDisabled>** property to the project file with a setting of `true`:
If a *web.config* file is in the project, it's transformed with the correct *processPath* and *arguments* to configure the [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module) and moved to [published output](xref:host-and-deploy/directory-structure). The transformation doesn't modify IIS configuration settings in the file.
### web.config location
.NET Core apps are hosted via a reverse proxy between IIS and the Kestrel server. In order to create the reverse proxy, the *web.config* file must be present at the content root path (typically the app base path) of the deployed app, which is the website physical path provided to IIS. The *web.config* file is required at the root of the app to enable the publishing of multiple apps using Web Deploy.
Sensitive files exist on the app's physical path, including subfolders, such as *\<assembly_name>.runtimeconfig.json*, *\<assembly_name>.xml* (XML Documentation comments), and *\<assembly_name>.deps.json*. When the *web.config* file is present and configures the site, IIS prevents these sensitive files from being served. **Therefore, it's important that the *web.config* file isn't accidently renamed or removed from the deployment.**
## Create the IIS Website
1. On the target IIS system, create a folder to contain the app's published folders and files, which are described in [Directory Structure](xref:host-and-deploy/directory-structure).
2. Within the folder, create a *logs* folder to hold stdout logs when stdout logging is enabled. If the app is deployed with a *logs* folder in the payload, skip this step. For instructions on how to make MSBuild create the *logs* folder, see the [Directory structure](xref:host-and-deploy/directory-structure) topic.
3. In **IIS Manager**, create a new website. Provide a **Site name** and set the **Physical path** to the app's deployment folder. Provide the **Binding** configuration and create the website.
4. Set the application pool to **No Managed Code**. ASP.NET Core runs in a separate process and manages the runtime.
5. Open the **Add Website** window.
![Select 'Add Website' from the Sites contextual menu.](index/_static/add-website-context-menu-ws2016.png)
6. Configure the website.
![Supply the Site name, physical path, and Host name in the Add Website step.](index/_static/add-website-ws2016.png)
7. In the **Application Pools** panel, open the **Edit Application Pool** window by right-clicking on the website's app pool and selecting **Basic Settings...** from the popup menu.
![Select Basic Settings from the contextual menu of the Application Pool.](index/_static/apppools-basic-settings-ws2016.png)
8. Set the **.NET CLR version** to **No Managed Code**.
![Set No Managed Code for the .NET CLR Version.](index/_static/edit-apppool-ws2016.png)
Note: Setting the **.NET CLR version** to **No Managed Code** is optional. ASP.NET Core doesn't rely on loading the desktop CLR.
9. Confirm the process model identity has the proper permissions.
If the default identity of the app pool (**Process Model** > **Identity**) is changed from **ApplicationPoolIdentity** to another identity, verify that the new identity has the required permissions to access the app's folder, database, and other required resources.
## Deploy the app
Deploy the app to the folder created on the target IIS system. [Web Deploy](/iis/publish/using-web-deploy/introduction-to-web-deploy) is the recommended mechanism for deployment.
Confirm that the published app for deployment isn't running. Files in the *publish* folder are locked when the app is running. Locked files can't be overwritten. To release locked files in a deployment, stop the app pool:
* Manually in the IIS Manager on the server.
* Using Web Deploy and referencing `Microsoft.NET.Sdk.Web` in the project file. An *app_offline.htm* file is placed at the root of the web app directory. When the file is present, the ASP.NET Core Module gracefully shuts down the app and serves the *app_offline.htm* file during the deployment. For more information, see the [ASP.NET Core Module configuration reference](xref:host-and-deploy/aspnet-core-module#appofflinehtm).
* Use PowerShell to stop and restart the app pool (requires PowerShell 5 or later):
See the [Visual Studio publish profiles for ASP.NET Core app deployment](xref:host-and-deploy/visual-studio-publish-profiles#publish-profiles) topic to learn how to create a publish profile for use with Web Deploy. If the hosting provider supplies a Publish Profile or support for creating one, download their profile and import it using the Visual Studio **Publish** dialog.
[Web Deploy](/iis/publish/using-web-deploy/introduction-to-web-deploy) can also be used outside of Visual Studio from the command line. For more information, see [Web Deployment Tool](/iis/publish/using-web-deploy/use-the-web-deployment-tool).
### Alternatives to Web Deploy
Use any of several methods to move the app to the hosting system, such as Xcopy, Robocopy, or PowerShell. Visual Studio users may use the [Publish Samples](https://github.com/aspnet/vsweb-publish/blob/master/samples/samples.md).
## Browse the website
![The Microsoft Edge browser has loaded the IIS startup page.](index/_static/browsewebsite.png)
## Data protection
Data Protection is used by several ASP.NET middlewares, including those used in authentication. Even if Data Protection APIs aren't called from user's code, Data Protection should be configured with a deployment script or in user code to create a persistent key store. If data protection isn't configured, the keys are held in memory and discarded when the app restarts.
If the keyring is stored in memory when the app restarts:
* All forms authentication tokens are invalidated.
* Users are required to sign in again on their next request.
* Any data protected with the keyring can no longer be decrypted.
To configure Data Protection under IIS, use **one** of the following approaches:
### Create a Data Protection Registry Hive
Data Protection keys used by ASP.NET apps are stored in registry hives external to the apps. To persist the keys for a given app, create a registry hive for the app pool.
For standalone, non-webfarm IIS installations, the [Data Protection Provision-AutoGenKeys.ps1 PowerShell script](https://github.com/aspnet/DataProtection/blob/dev/Provision-AutoGenKeys.ps1) can be used for each app pool used with an ASP.NET Core app. This script creates a special registry key in the HKLM registry that's ACLed only to the worker process account. Keys are encrypted at rest using DPAPI with a machine-wide key.
In web farm scenarios, an app can be configured to use a UNC path to store its data protection keyring. By default, the data protection keys are not encrypted. Ensure that the file permissions for such a share are limited to the Windows account the app runs as. In addition, an X509 certificate can be used to protect keys at rest. Consider a mechanism to allow users to upload certificates: Place certificates into the user's trusted certificate store and ensure they're available on all machines where the user's app runs. See [Configuring Data Protection](xref:security/data-protection/configuration/overview) for details.
### Configure the IIS Application Pool to load the user profile
This setting is in the **Process Model** section under the **Advanced Settings** for the app pool. Set Load User Profile to `True`. This stores keys under the user profile directory and protects them using DPAPI with a key specific to the user account used for the app pool.
### Use the file system as a key ring store
Adjust the app code to [use the file system as a key ring store](xref:security/data-protection/configuration/overview). Use an X509 certificate to protect the keyring and ensure the certificate is a trusted certificate. If it's a self signed certificate, place the certificate in the Trusted Root store.
When using IIS in a web farm:
* Use a file share that all machines can access.
* Deploy an X509 certificate to each machine. Configure [data protection in code](xref:security/data-protection/configuration/overview).
### Set a machine-wide policy for data protection
The data protection system has limited support for setting a default [machine-wide policy](xref:security/data-protection/configuration/machine-wide-policy) for all apps that consume the Data Protection APIs. See the [data protection](xref:security/data-protection/index) documentation for more details.
## Configuration of sub-applications
Sub-apps added under the root app shouldn't include the ASP.NET Core Module as a handler. If the module is added as a handler in a sub-app's *web.config* file, a 500.19 (Internal Server Error) referencing the faulty config file is received when attempting to browse the sub-app. The following example shows the contents of a published *web.config* file for an ASP.NET Core sub-app:
```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<aspNetCoreprocessPath="dotnet"
arguments=".\<assembly_name>.dll"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
```
When hosting a non-ASP.NET Core sub-app underneath an ASP.NET Core app, explicitly remove the inherited handler in the sub-app *web.config* file:
```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<removename="aspNetCore"/>
</handlers>
<aspNetCoreprocessPath="dotnet"
arguments=".\<assembly_name>.dll"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
```
For more information on configuring the ASP.NET Core Module, see the [Introduction to ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module) topic and the [ASP.NET Core Module configuration reference](xref:host-and-deploy/aspnet-core-module).
## Configuration of IIS with web.config
IIS configuration is influenced by the **\<system.webServer>** section of *web.config* for those IIS features that apply to a reverse proxy configuration. If IIS is configured at the system level to use dynamic compression, that setting can be disabled for an app with the **\<urlCompression>** element in the app's *web.config* file. For more information, see the [configuration reference for \<system.webServer>](https://docs.microsoft.com/iis/configuration/system.webServer/), [ASP.NET Core Module Configuration Reference](xref:host-and-deploy/aspnet-core-module) and [Using IIS Modules with ASP.NET Core](xref:host-and-deploy/iis/modules). If there's a need to set environment variables for individual apps running in isolated app pools (supported on IIS 10.0+), see the *AppCmd.exe command* section of the [Environment Variables \<environmentVariables>](/iis/configuration/system.applicationHost/applicationPools/add/environmentVariables/#appcmdexe) topic in the IIS reference documentation.
## Configuration sections of web.config
Configruation sections of ASP.NET Framework apps in *web.config* aren't used by ASP.NET Core apps for configuration:
* **\<system.web>**
* **\<appSettings>**
* **\<connectionStrings>**
* **\<location>**
ASP.NET Core apps are configured using other configuration providers. For more information, see [Configuration](xref:fundamentals/configuration/index).
## Application Pools
When hosting multiple websites on a single system, isolate the apps from each other by running each app in its own app pool. The IIS **Add Website** dialog defaults to this configuration. When **Site name** is provided, the text is automatically transferred to the **Application pool** textbox. A new app pool is created using the site name when the website 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+, 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](index/_static/apppool-identity.png)
The IIS management process creates a secure identifier with the name of the app pool in the Windows Security System. Resources can be secured by using this identity; however, this identity isn't a real user account and won't show up in 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:
1. Open Windows Explorer and navigate to the directory.
2. Right-click on the directory and select **Properties**.
3. Under the **Security** tab, select the **Edit** button and then the **Add** button.
4. Select the **Locations** button and make sure the system is selected.
5. Enter **IIS AppPool\DefaultAppPool** in **Enter the object names to select** textbox.
![Select users or groups dialog for the app folder](index/_static/select-users-or-groups-1.png)
6. Select the **Check Names** button. Select **OK**.
![Select users or groups dialog for the app folder](index/_static/select-users-or-groups-2.png)
This can also be accomplished via a command prompt using the **ICACLS** tool: