IIS has a reputation for being old and fiddly. The truth is more boring: it's a solid web server with a slightly unfamiliar configuration model. Once you know the three concepts that matter — sites, application pools, and bindings — the rest is just clicking around. This post walks you through a clean install on Windows Server, deploying an ASP.NET Core app, and wiring up HTTPS.

1. Install the role

On a fresh Windows Server, you can enable IIS in one PowerShell line:

Install-WindowsFeature -Name Web-Server `
    -IncludeManagementTools `
    -IncludeAllSubFeature

On Windows 10 or 11 (for local development), use:

Enable-WindowsOptionalFeature -Online `
    -FeatureName IIS-WebServerRole, IIS-WebServer, IIS-ManagementConsole

Browse to http://localhost and you should see the default IIS welcome page. That confirms the worker process is running.

2. Install the ASP.NET Core hosting bundle

IIS doesn't host .NET Core directly; it acts as a reverse proxy in front of dotnet.exe via the ASP.NET Core Module. Download the Hosting Bundle matching your target framework version and run it. Then restart the IIS service:

net stop was /y
net start w3svc

3. Create an application pool

Application pools isolate sites from each other. Each pool runs as its own worker process (w3wp.exe) under its own identity. For an ASP.NET Core site, set the .NET CLR version to No Managed Code — the runtime is inside your published binary, not the pool.

Import-Module WebAdministration

New-WebAppPool -Name "MyApp"
Set-ItemProperty IIS:\AppPools\MyApp `
    -Name managedRuntimeVersion -Value ""
Set-ItemProperty IIS:\AppPools\MyApp `
    -Name processModel.identityType -Value ApplicationPoolIdentity

4. Publish and create the site

Publish your app to a folder the IIS user can read:

dotnet publish -c Release -o C:\inetpub\sites\myapp

Then create a site bound to port 80:

New-Website -Name "MyApp" `
    -PhysicalPath "C:\inetpub\sites\myapp" `
    -ApplicationPool "MyApp" `
    -Port 80 -HostHeader "myapp.local"

Add myapp.local to your hosts file pointing at 127.0.0.1 for local testing.

5. HTTPS with a real certificate

The simplest production-grade approach is win-acme, a Let's Encrypt client built specifically for IIS. Install it once, run wacs.exe, choose your site, and it'll request, install, and renew the certificate automatically. The HTTPS binding is wired up for you.

Don't forget firewall rules. By default, Windows Server allows HTTP/HTTPS on the public profile when the role is installed — but if you locked down the firewall first, run New-NetFirewallRule -DisplayName "HTTPS" -LocalPort 443 -Protocol TCP -Action Allow.

6. Logging and the first failure

When something breaks, look in three places, in order:

  1. The browser response — a 502.5 means the worker process couldn't start.
  2. IIS logs at C:\inetpub\logs\LogFiles\W3SVC{n}\ — request-level data.
  3. Event Viewer → Application — the ASP.NET Core Module logs startup errors here.

Enable stdout logging in your web.config for richer detail while you debug. Just remember to disable it once things are stable; it grows fast.

You're done

That's a complete, functional IIS site. From here you can layer in URL rewrites, response compression, output caching, and Windows Authentication — all configured through web.config sections or the IIS Manager GUI. Both edit the same XML; the GUI just provides better tab-completion.

Need help productionizing a real deployment? Our coaching covers IIS hardening, load-balancing with ARR, and CI/CD pipelines from Azure DevOps to on-prem boxes. Talk to a mentor if that's where you're stuck.