IIS is Microsoft's web server — built into every Windows Server SKU, integrated with Windows authentication and AD, and the right answer when you host .NET applications. This guide installs it, drops a static site, and adds an HTTPS binding with a Let's Encrypt cert via win-acme.
Prerequisites
- Windows Server 2019 / 2022 with admin PowerShell.
- A DNS record pointing at the server (for the TLS step).
- An idea of where your site root lives — we will use
D:\Sites\example.sa.
Step 1: Install the IIS role
Install-WindowsFeature -Name Web-Server, Web-Common-Http, Web-Static-Content, `
Web-Default-Doc, Web-Dir-Browsing, Web-Http-Errors, `
Web-Http-Logging, Web-Stat-Compression, Web-Filtering, `
Web-Mgmt-Console `
-IncludeManagementTools
For .NET apps add:
Install-WindowsFeature -Name Web-Asp-Net45, Web-Net-Ext45, Web-ISAPI-Ext, Web-ISAPI-Filter
For Windows authentication on intranet sites:
Install-WindowsFeature -Name Web-Windows-Auth
Step 2: Verify and visit the default site
Get-Service W3SVC, WAS
Start-Service W3SVC
Invoke-WebRequest http://localhost/ -UseBasicParsing | Select-Object StatusCode
A 200 with the IIS welcome page = healthy.
Step 3: Create a site root and a site
New-Item -Path "D:\Sites\example.sa" -ItemType Directory -Force
Set-Content -Path "D:\Sites\example.sa\index.html" `
-Value '<h1>Hello from SKYLINE</h1>'
Import-Module WebAdministration
New-WebAppPool -Name "example.sa"
Set-ItemProperty -Path IIS:\AppPools\example.sa `
-Name managedRuntimeVersion -Value "" # set "v4.0" for .NET
New-Website -Name "example.sa" `
-HostHeader "example.sa" `
-PhysicalPath "D:\Sites\example.sa" `
-ApplicationPool "example.sa" `
-Port 80
Hit it:
Invoke-WebRequest "http://example.sa/" -UseBasicParsing | Select-Object StatusCode
Step 4: Open the firewall
Get-NetFirewallRule -DisplayGroup "World Wide Web Services (HTTP)" | Enable-NetFirewallRule
Get-NetFirewallRule -DisplayGroup "Secure World Wide Web Services (HTTPS)" | Enable-NetFirewallRule
Step 5: TLS with win-acme (Let's Encrypt for Windows)
# Download win-acme
$ver = "v2.2.9.1701"
Invoke-WebRequest "https://github.com/win-acme/win-acme/releases/download/$ver/win-acme.$ver.x64.trimmed.zip" `
-OutFile "$env:TEMP\wacs.zip"
Expand-Archive "$env:TEMP\wacs.zip" -DestinationPath "C:\Tools\win-acme" -Force
cd C:\Tools\win-acme
# Interactive — pick option N (Create renewal with simple defaults)
.\wacs.exe
win-acme adds the HTTPS binding to the matching IIS site, installs the certificate to the Windows cert store, and registers a scheduled task that renews 30 days before expiry. Verify:
Get-WebBinding -Name "example.sa"
Get-ChildItem Cert:\LocalMachine\WebHosting | Select-Object Subject, NotAfter
schtasks /Query /TN "win-acme renew (acme-v02.api.letsencrypt.org)"
Step 6: Tighten the defaults
# Disable directory browsing
Set-WebConfigurationProperty -Filter "/system.webServer/directoryBrowse" `
-Name "enabled" -Value "false" -PSPath "IIS:\Sites\example.sa"
# Remove the Server header
Set-WebConfigurationProperty -Filter "/system.webServer/security/requestFiltering" `
-Name "removeServerHeader" -Value "True" `
-PSPath "IIS:\Sites\example.sa"
# Add HSTS once you are HTTPS-only
Add-WebConfigurationProperty -PSPath "IIS:\Sites\example.sa" `
-Filter "system.webServer/httpProtocol/customHeaders" `
-Name "." `
-Value @{name='Strict-Transport-Security';value='max-age=63072000; includeSubDomains'}
Verify
Invoke-WebRequest "https://example.sa/" -UseBasicParsing | `
Select-Object -ExpandProperty Headers | Format-List
Get-WebBinding | Format-Table
Get-Website | Format-Table Name, State, PhysicalPath
Conclusion
IIS is fine for static sites, .NET apps, and Windows-auth intranet portals. For non-.NET production workloads (Node, Python, Go), still install IIS as a reverse proxy front, with Application Request Routing forwarding to the upstream — but that is a separate guide.
Next steps
- Tighten the box with Windows Firewall via PowerShell.
- For Active Directory integration see Promote Windows Server to a DC.
- Schedule deploys/cleanups with Windows Task Scheduler.
Comments
0 total · 0 threads