Home / Windows Server / Windows Server IIS and Web Hosting: Enterprise Web Services
Windows Server

Windows Server IIS and Web Hosting: Enterprise Web Services

Deploy enterprise web services with IIS configuration, application pool management, SSL/TLS certificates, URL rewrite rules, Application Request Routing for ...

What you will learn

Practical execution with concise explanations, real implementation patterns, and production-ready recommendations.

Windows Server IIS and Web Hosting: Enterprise Web Services

Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" -Filter "system.applicationHost/sites/site[@name='ContosoWeb']/hsts" -Name "." -Value @{enabled=$true;max-age=31536000;includeSubDomains=$true}


## URL Rewrite Module

### Installing URL Rewrite





```powershell
## Download and install URL Rewrite module




## https://www.iis.net/downloads/microsoft/url-rewrite





## Or use Web Platform Installer




## Install-Module -Name WebPlatformInstaller




## Install-Package -Name UrlRewrite2

Creating Rewrite Rules

Creating Rewrite Rules

Figure: Outlook Web – mail rules, shared calendars, and resource booking.





## HTTP to HTTPS redirect
Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/rewrite/rules" `
-Name "." `
-Value @{name='HTTP to HTTPS';stopProcessing='True'}

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/rewrite/rules/rule[@name='HTTP to HTTPS']/match" `
-Name "url" -Value "(.*)"

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/rewrite/rules/rule[@name='HTTP to HTTPS']/conditions" `




-Name "." `
-Value @{input='{HTTPS}';pattern='off'}

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/rewrite/rules/rule[@name='HTTP to HTTPS']/action" `
-Name "type" -Value "Redirect"```
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/rewrite/rules/rule[@name='HTTP to HTTPS']/action" `
-Name "url" -Value "https://{HTTP_HOST}/{R:1}"

Canonical hostname (www to non-www)

Example web.config snippet:

Example web.config snippet:

Figure: Configuration and management dashboard with status overview.

$rewriteConfig = @"

<rule name="Canonical Hostname" stopProcessing="true">
  <match url="(.*)" />
  <conditions>
    <add input="{HTTP_HOST}" pattern="^www\.contoso\.com$" />
  </conditions>
  <action type="Redirect" url="https://contoso.com/{R:1}" redirectType="Permanent" />
</rule>```
  </rules>
</rewrite>
"@





Load Balancing with ARR

Installing Application Request Routing

## Download and install ARR




## https://www.iis.net/downloads/microsoft/application-request-routing





## Enable proxy mode
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" -Filter "system.webServer/proxy" -Name "enabled" -Value $true





Creating Server Farm

Creating Server Farm

Figure: Configuration and management dashboard with status overview.





## Server farm configuration requires IIS Manager or web.config editing





## Example: Configure server farm in applicationHost.config
$serverFarmConfig = @"
<webFarms>
  <webFarm name="ContosoFarm" enabled="true">
```text
<server address="web01.contoso.com" enabled="true" />
<server address="web02.contoso.com" enabled="true" />
<applicationRequestRouting>
  <affinity useCookie="true" cookieName="ARRAffinity" />
  <loadBalance algorithm="WeightedRoundRobin" />
  <healthCheck url="http://localhost/health" interval="00:00:30" />
</applicationRequestRouting>```
  </webFarm>
</webFarms>
"@





## URL rewrite rule to route to farm
$farmRouting = @"
<rule name="ARR_ContosoFarm_loadbalance" patternSyntax="Wildcard" stopProcessing="true">
  <match url="*" />
  <action type="Rewrite" url="http://ContosoFarm/{R:0}" />
</rule>
"@





Health Monitoring





## Health check configuration




## Create health endpoint in application (e.g., /health)




## Returns HTTP 200 when healthy





## Monitor server farm health




## Get-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" -Filter "webFarms/webFarm[@name='ContosoFarm']/server" | Select-Object address, enabled, state

Get-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" -Filter "webFarms/webFarm[@name='ContosoFarm']/server" | Select-Object address, enabled, state

Web Farm Configuration

Shared Configuration

## Export IIS configuration
Export-IISConfiguration -PhysicalPath "\\fileserver\IISConfig" `
```text
-DontExportKeys $false `
-Force

On additional web servers, import configuration

Enable-IISSharedConfig -PhysicalPath "\fileserver\IISConfig" `

-KeyEncryptionPassword (ConvertTo-SecureString "P@ssw0rd123!" -AsPlainText -Force) `
-Force

View shared config status

Get-IISSharedConfig


## Content Synchronization

```powershell




## Synchronize content using Robocopy
$syncScript = @"




## Sync web content from primary to secondary servers
`$source = '\\web01\C$\inetpub\wwwroot\ContosoWeb'
`$destinations = @('\\web02\C$\inetpub\wwwroot\ContosoWeb', '\\web03\C$\inetpub\wwwroot\ContosoWeb')





foreach (`$dest in `$destinations) {
```text
robocopy `$source `$dest /MIR /R:3 /W:5 /MT:8 /LOG:C:\Logs\Sync.log```
}
"@

$syncScript | Out-File "C:\Scripts\SyncContent.ps1"

## Schedule content sync
$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' `
```text
-Argument '-ExecutionPolicy Bypass -File C:\Scripts\SyncContent.ps1'```
$trigger = New-ScheduledTaskTrigger -Daily -At 3am
Register-ScheduledTask -TaskName "IIS Content Sync" -Action $action -Trigger $trigger -User "SYSTEM"





Security Best Practices

Request Filtering

## Configure request filtering
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/security/requestFiltering" `
-Name "allowDoubleEscaping" -Value $false

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/security/requestFiltering" `
-Name "allowHighBitCharacters" -Value $false

Block file extensions

Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/security/requestFiltering/fileExtensions" `
-Name "." -Value @{fileExtension='.config';allowed=$false}

Block dangerous strings

Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/security/requestFiltering/denyUrlSequences" `
-Name "." -Value @{sequence='..'}

Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/security/requestFiltering/denyUrlSequences" `
-Name "." -Value @{sequence='<script'}





## IP Restrictions

```powershell




## Allow only specific IP addresses
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/security/ipSecurity" `
-Name "allowUnlisted" -Value $false

Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/security/ipSecurity" `
-Name "." -Value @{ipAddress='192.168.1.0';subnetMask='255.255.255.0';allowed=$true}

Block specific IP

Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/security/ipSecurity" `
-Name "." -Value @{ipAddress='10.0.0.50';allowed=$false}





## Authentication Configuration

```powershell




## Disable anonymous authentication
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/security/authentication/anonymousAuthentication" `
-Name "enabled" -Value $false

Enable Windows authentication

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/security/authentication/windowsAuthentication" `
-Name "enabled" -Value $true

Configure authorization

Add-WebConfiguration -Filter "/system.webServer/security/authorization" `

-Value @{accessType='Allow';roles='CONTOSO\Web Users'} `
-PSPath "IIS:\" -Location "ContosoWeb"

Remove-WebConfiguration -Filter "/system.webServer/security/authorization/add[@users='*']" `

-PSPath "IIS:\" -Location "ContosoWeb"





## Performance Optimization

### Static Compression





```powershell
## Enable static compression
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" `
```text
-Filter "system.webServer/httpCompression" `
-Name "staticCompressionEnableCpuUsage" -Value 90

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" `

-Filter "system.webServer/httpCompression/scheme[@name='gzip']" `
-Name "staticCompressionLevel" -Value 9

Add file types to compress

Add-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" `

-Filter "system.webServer/httpCompression/staticTypes" `
-Name "." -Value @{mimeType='application/json';enabled=$true}





## Output Caching

```powershell




## Enable output caching
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/caching" `
-Name "enabled" -Value $true

Add cache rule

Add-WebConfiguration -Filter "/system.webServer/caching/profiles" `

-Value @{extension='.html';policy='CacheUntilChange';kernelCachePolicy='CacheUntilChange'} `
-PSPath "IIS:\" -Location "ContosoWeb"

Set cache duration

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/staticContent/clientCache" `
-Name "cacheControlMode" -Value "UseMaxAge"

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.webServer/staticContent/clientCache" `
-Name "cacheControlMaxAge" -Value "7.00:00:00"  # 7 days





## HTTP/2 Configuration

```powershell




## Enable HTTP/2 (enabled by default on Windows Server 2016+)
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" `
```text
-Filter "system.applicationHost/sites/site[@name='ContosoWeb']/bindings/binding[@protocol='https']" `
-Name "sslFlags" -Value 0  # HTTP/2 requires SNI

Verify HTTP/2 is enabled

Verify HTTP/2 is enabled

Figure: Configuration and management dashboard with status overview.

Get-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" `

-Filter "system.webServer/serverRuntime" `
-Name "enabled"





## Application Initialization

```powershell




## Enable application initialization
Set-ItemProperty -Path "IIS:\AppPools\ContosoAppPool" -Name "startMode" -Value "AlwaysRunning"





Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/applicationInitialization" `
-Name "doAppInitAfterRestart" -Value $true

Add initialization page

Add-WebConfiguration -Filter "/system.webServer/applicationInitialization/add" `

-Value @{initializationPage='/warmup.aspx'} `
-PSPath "IIS:\" -Location "ContosoWeb"





## Monitoring IIS

### IIS Logs





```powershell
## Configure logging
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `
```text
-Filter "system.webServer/httpLogging" `
-Name "dontLog" -Value $false

Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST/ContosoWeb" `

-Filter "system.applicationHost/sites/site[@name='ContosoWeb']/logFile" `
-Name "directory" -Value "D:\IISLogs"

View recent errors

Get-Content "C:\inetpub\logs\LogFiles\W3SVC1*.log" -Tail 50 | Where-Object { $_ -like '500' }


## Performance Counters

```powershell




## Monitor IIS performance counters
$counters = @(
```text
'\Web Service(_Total)\Current Connections'
'\Web Service(_Total)\Bytes Total/sec'
'\ASP.NET Applications(__Total__)\Requests/Sec'
'\ASP.NET Applications(__Total__)\Request Execution Time'
'\Process(w3wp)\% Processor Time'
'\Process(w3wp)\Private Bytes'```
)





Get-Counter -Counter $counters -SampleInterval 5 -MaxSamples 10 | 
```powershell
ForEach-Object { $_.CounterSamples | Format-Table -AutoSize }

## Architecture Decision and Tradeoffs

When designing server infrastructure solutions with Windows Server, consider these key architectural trade-offs:

| Approach | Best For | Tradeoff |
|----------|----------|----------|
| Managed / platform service | Rapid delivery, reduced ops burden | Less customisation, potential vendor lock-in |
| Custom / self-hosted | Full control, advanced tuning | Higher operational overhead and cost |

> **Recommendation:** Start with the managed approach for most workloads and move to custom only when specific requirements demand it.

## Validation and Versioning

- Last validated: April 2026
- Validate examples against your tenant, region, and SKU constraints before production rollout.
- Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.

## Security and Governance Considerations

- Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
- Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
- Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.

## Cost and Performance Notes

- Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
- Baseline performance with synthetic and real-user checks before and after major changes.
- Scale resources with measured thresholds and revisit sizing after usage pattern changes.

## Official Microsoft References

- https://learn.microsoft.com/windows-server/
- https://learn.microsoft.com/windows/security/
- https://learn.microsoft.com/azure/azure-arc/

## Public Examples from Official Sources

- These examples are sourced from official public Microsoft documentation and sample repositories.
- Documentation examples: https://learn.microsoft.com/windows-server/
- Sample repositories: https://github.com/microsoft/Windows-Containers
- Prefer adapting these examples to your tenant, subscriptions, and governance requirements before production use.

## Key Takeaways

- IIS provides enterprise web hosting on Windows Server
- Application pools isolate applications for security and stability
- SSL/TLS certificates secure web traffic with HTTPS
- URL Rewrite handles redirects and URL normalization
- ARR delivers load balancing across web servers
- Web farms share configuration and content
- Security features include request filtering and IP restrictions
- Performance optimization includes compression, caching, and HTTP/2





## Next Steps

- Deploy IIS with application pool isolation
- Configure SSL certificates for HTTPS
- Implement URL rewrite rules
- Set up load balancing with ARR
- Configure web farm with shared configuration
- Harden IIS security settings
- Optimize performance with compression and caching


## Additional Resources

- [IIS Documentation](https://learn.microsoft.com/iis/)
- [Application Request Routing](https://learn.microsoft.com/iis/extensions/planning-for-arr/application-request-routing-version-2-overview)
- [URL Rewrite Module](https://learn.microsoft.com/iis/extensions/url-rewrite-module/url-rewrite-module-configuration-reference)
- [IIS Security Best Practices](https://learn.microsoft.com/iis/get-started/whats-new-in-iis-10/http2-on-iis)


---

*Host. Secure. Scale. Optimize.*

Discussion