Skip to content

Windows

IIS Web Server

Internet Information Services (IIS) is the web server built into Windows Server. It hosts static sites, ASP.NET / ASP.NET Core apps, and reverse-proxied back ends, managed through a GUI, PowerShell, or appcmd.

Tested on

Windows Server 2022 with IIS 10.0. The workflow is identical on Windows Server 2019 and 2016 (also IIS 10.0).

Installing IIS

IIS is the Web Server (IIS) role. Install it with PowerShell:

# Core web server plus IIS Manager and the PowerShell module
Install-WindowsFeature -Name Web-Server -IncludeManagementTools

# Common extras you will likely want
Install-WindowsFeature Web-Asp-Net45, Web-Windows-Auth, Web-Http-Redirect

Or via Server Manager -> Add Roles and Features -> Web Server (IIS), selecting role services on the wizard's Role Services page.

Verify with Get-WindowsFeature Web-Server and browse to http://localhost - you should see the IIS default page.

IIS Manager

IIS Manager (inetmgr / Server Manager -> Tools -> Internet Information Services (IIS) Manager) is the central console. The left Connections pane shows the server, an Application Pools node, and a Sites node. The middle pane shows feature icons for the selected item; the right Actions pane has the contextual commands (Add Website, Bindings, Restart, ...).

The PowerShell equivalent is the WebAdministration module (Import-Module WebAdministration), which exposes an IIS:\ drive plus cmdlets like New-Website, New-WebAppPool, and New-WebBinding.

Sites, bindings, and application pools

Three concepts do the heavy lifting:

  • Site - a hosted web application with a physical path (the folder of files) and one or more bindings.
  • Binding - the combination of protocol + IP address + port + host name that tells IIS which incoming requests belong to this site. The host name lets many sites share one IP and port 80/443 (name-based hosting).
  • Application pool - the worker process(es) (w3wp.exe) a site runs in, with its own identity and settings.
Binding examples (all can coexist on one server):
  http   *:80:www.example.com         -> Site "Example"
  https  *:443:www.example.com        -> Site "Example"  (needs a certificate)
  http   10.0.0.5:8080:               -> Site "Internal" (IP + port, no host name)

Why application pools matter

Each application pool runs in a separate process with its own identity. This gives you:

  • Isolation - one site crashing or leaking memory does not take down sites in other pools.
  • Security - a pool can run as the low-privilege ApplicationPoolIdentity (a virtual account IIS APPPOOL\<PoolName>), so you grant filesystem access to exactly that site and no more.
  • Independent lifecycle - you can recycle or stop one pool without touching others, and set per-pool .NET CLR version and recycling rules.

Give each site (or each trust boundary) its own app pool.

Adding a site

GUI

  1. In IIS Manager, right-click Sites -> Add Website....
  2. Site name: Example. A matching app pool is created automatically.
  3. Physical path: C:\inetpub\sites\example (the folder with your files).
  4. Binding: Type http, IP All Unassigned, Port 80, Host name www.example.com.
  5. OK. Put an index.html (or app files) in the path and browse to it.

PowerShell

Import-Module WebAdministration

New-Item 'C:\inetpub\sites\example' -ItemType Directory
New-WebAppPool -Name 'ExamplePool'
New-Website -Name 'Example' -PhysicalPath 'C:\inetpub\sites\example' `
    -ApplicationPool 'ExamplePool' -HostHeader 'www.example.com' -Port 80

# Add an HTTPS binding (certificate attached separately, see below)
New-WebBinding -Name 'Example' -Protocol https -Port 443 -HostHeader 'www.example.com'

Grant the pool identity read access to the content: icacls C:\inetpub\sites\example /grant 'IIS APPPOOL\ExamplePool:(OI)(CI)RX' (see File sharing and permissions for ACLs).

SSL/TLS bindings and certificates

HTTPS needs a certificate bound to the site's https binding. The conceptual flow - key pair, CSR, trusted CA, certificate, then bind - is the same as on Linux; see HTTPS with Let's Encrypt for the underlying ideas.

  1. Get a certificate into the server's Local Machine -> Personal store (import a PFX, request from an internal CA, or use a tool like win-acme for public ACME/Let's Encrypt certs).
  2. In IIS Manager, select the site -> Bindings... -> Add -> Type https, port 443, host name, then pick the certificate from the SSL certificate list. Enable Require Server Name Indication (SNI) to host multiple HTTPS sites on one IP.
# Bind an installed cert (by thumbprint) to the site's https binding
$cert = Get-ChildItem Cert:\LocalMachine\My |
        Where-Object Subject -like '*www.example.com*'
New-Item -Path "IIS:\SslBindings\!443!www.example.com" -Value $cert -SSLFlags 1

-SSLFlags 1 enables SNI. Use Edit Bindings to add an https binding first if you have not already.

Authentication and authorization

In the site's Authentication feature you enable/disable methods:

  • Anonymous - on by default; serves content with no logon (public sites).
  • Basic - prompts for username/password; only over HTTPS (credentials are base64, not encrypted).
  • Windows Authentication - transparent SSO for domain users (intranets); needs the Web-Windows-Auth role service.

The Authorization Rules feature then allows/denies specific users or roles. A common intranet setup: disable Anonymous, enable Windows Auth, and add an Allow rule for a domain group.

# Example: turn off anonymous, turn on Windows auth for a site
Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/anonymousAuthentication' `
    -Name enabled -Value $false -PSPath 'IIS:\Sites\Example'
Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/windowsAuthentication' `
    -Name enabled -Value $true -PSPath 'IIS:\Sites\Example'

Logs

By default IIS writes W3C access logs per site under:

C:\inetpub\logs\LogFiles\W3SVC<SiteID>\

The <SiteID> matches the site's ID in IIS Manager. Configure fields, rollover, and location in the site's Logging feature. Failed Request Tracing (a separate role service) captures detailed traces for specific status codes when you are debugging.

iisreset and recycling

iisreset            # stop+start the whole IIS service stack (all sites - disruptive)
iisreset /status    # show service states

# Per-site / per-pool control (preferred - scoped, less disruptive)
Restart-WebAppPool 'ExamplePool'     # recycle just one pool
Stop-Website  'Example'
Start-Website 'Example'

Recycling restarts a pool's worker process gracefully (finishing in-flight requests on the old process while a new one starts). App pools recycle automatically on a schedule and on config changes; tune this in the pool's Advanced Settings -> Recycling. Reach for iisreset only when you really need to restart everything - it briefly takes all sites offline.

IIS vs nginx

If you also run nginx on Linux, the roles map roughly like this:

IIS nginx
Platform Windows Server (role) Linux/Unix (package)
Config GUI + web.config / applicationHost.config text files (nginx.conf)
Process model App pools -> w3wp.exe worker(s) master + worker processes
Per-site isolation Application pools (own identity) typically one daemon, server {} blocks
Virtual hosts Site bindings (host/IP/port) server blocks + server_name
Restart/reload iisreset, recycle app pool nginx -s reload (graceful)
Native strength ASP.NET / .NET, Windows Auth static files, reverse proxy at scale

Both are production web servers; the binding/virtual-host and graceful-reload ideas carry over directly between them.

Verify your work

  1. Run Get-WindowsFeature Web-Server and confirm it shows Installed.
  2. Browse to http://localhost and confirm the IIS default page loads.
  3. After adding your site, browse to its host name (add a hosts-file entry if no DNS) and confirm your content loads; check Get-Website lists it.
  4. Add the HTTPS binding + certificate, browse https://www.example.com, and confirm the padlock / a valid certificate.
  5. Run Restart-WebAppPool 'ExamplePool', reload the site, and confirm it still serves. Check a request appears in C:\inetpub\logs\LogFiles\W3SVC<ID>\.

Summary

  • Install IIS with Install-WindowsFeature Web-Server -IncludeManagementTools; manage it in IIS Manager (inetmgr) or the WebAdministration module.
  • A site has a physical path and bindings (protocol + IP + port + host name); application pools isolate sites into separate worker processes with their own identity.
  • Add HTTPS by binding a certificate to an https binding (use SNI for many sites on one IP); the cert concepts match the Linux HTTPS page.
  • Control access with Authentication (Anonymous/Basic/Windows) plus Authorization Rules; logs live under C:\inetpub\logs\LogFiles\W3SVC<SiteID>\.
  • Prefer app-pool recycling / per-site start-stop over the disruptive iisreset. Versus nginx, bindings ~ server blocks and recycling ~ graceful reload. See also PowerShell basics.

Test yourself