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.
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:
- The browser response — a 502.5 means the worker process couldn't start.
- IIS logs at
C:\inetpub\logs\LogFiles\W3SVC{n}\— request-level data. - 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.