How to Host Multiple Websites with IIS Bindings on Windows Server 2022
One of IIS’s most powerful capabilities is the ability to host multiple websites on a single server, sharing the same IP address or using separate IP addresses, ports, or host headers to differentiate traffic. Windows Server 2022 with IIS 10 handles this through a combination of bindings and application pools. This guide covers every major approach to multi-site hosting on IIS with practical PowerShell commands.
How IIS Bindings Work
An IIS binding is a combination of four attributes that tell IIS which incoming requests to route to which site: protocol (http or https), IP address, port, and host header. When a request arrives, IIS reads these attributes from the HTTP request and matches it to the appropriate site. The binding tuple must be unique across all sites — no two sites can have an identical combination of protocol, IP, port, and host header.
The three primary methods for differentiating multiple sites are:
Host-header (name-based) hosting — multiple sites on the same IP and port, differentiated by the HTTP Host header the client sends. This is the most common approach and works with a single IP address.
Port-based hosting — multiple sites on the same IP but different port numbers. Useful for development or internal tools where custom ports are acceptable.
IP-based hosting — each site has a dedicated IP address, all on port 80/443. Required for legacy SSL/TLS configurations that predate SNI support.
Viewing Existing Bindings with Get-WebBinding
Before adding new bindings, inspect what is already configured. The Get-WebBinding cmdlet returns all bindings across all sites or for a specific site:
# List all bindings on all sites
Get-WebBinding
# List bindings for a specific site
Get-WebBinding -Name "Default Web Site"
# List only HTTP bindings across all sites
Get-WebBinding -Protocol "http"
# Filter by port
Get-WebBinding -Port 443
The output columns show the site name, protocol, binding information (in the format IP:Port:HostHeader), and whether SSL flags are set. An asterisk (*) in the IP field means all unassigned IP addresses.
Name-Based Virtual Hosting with Host Headers
Host-header based hosting is the standard approach for sharing one IP address across many domains. Create a separate site for each domain and give each a unique host header binding. Start by creating directories and sites:
# Create content directories
New-Item -Path "C:inetpubsite1" -ItemType Directory
New-Item -Path "C:inetpubsite2" -ItemType Directory
New-Item -Path "C:inetpubsite3" -ItemType Directory
# Create index files for testing
Set-Content "C:inetpubsite1index.html" "Site One
"
Set-Content "C:inetpubsite2index.html" "Site Two
"
Set-Content "C:inetpubsite3index.html" "Site Three
"
# Create application pools (one per site for isolation)
New-WebAppPool -Name "Site1Pool"
New-WebAppPool -Name "Site2Pool"
New-WebAppPool -Name "Site3Pool"
# Create websites with host header bindings
New-WebSite -Name "Site1" -PhysicalPath "C:inetpubsite1" -Port 80 -HostHeader "site1.example.com" -ApplicationPool "Site1Pool"
New-WebSite -Name "Site2" -PhysicalPath "C:inetpubsite2" -Port 80 -HostHeader "site2.example.com" -ApplicationPool "Site2Pool"
New-WebSite -Name "Site3" -PhysicalPath "C:inetpubsite3" -Port 80 -HostHeader "site3.example.com" -ApplicationPool "Site3Pool"
Grant IIS the necessary NTFS permissions for each app pool identity:
icacls "C:inetpubsite1" /grant "IIS AppPoolSite1Pool:(OI)(CI)RX"
icacls "C:inetpubsite2" /grant "IIS AppPoolSite2Pool:(OI)(CI)RX"
icacls "C:inetpubsite3" /grant "IIS AppPoolSite3Pool:(OI)(CI)RX"
Adding Bindings with New-WebBinding
Use New-WebBinding to add additional bindings to an existing site. A site can have multiple bindings — for example, to respond to both the bare domain and the www subdomain:
# Add www binding to Site1
New-WebBinding -Name "Site1" -Protocol "http" -Port 80 -HostHeader "www.site1.example.com" -IPAddress "*"
# Add a second host alias
New-WebBinding -Name "Site1" -Protocol "http" -Port 80 -HostHeader "site1-alias.example.com" -IPAddress "*"
Confirm all bindings were added:
Get-WebBinding -Name "Site1" | Format-Table protocol, bindingInformation
Modifying Bindings with Set-WebBinding
Set-WebBinding updates an existing binding’s properties without removing and recreating it. This is useful for changing a host header on a live binding:
# Change the host header on an existing binding
Set-WebBinding -Name "Site1" -BindingInformation "*:80:site1-alias.example.com" -PropertyName "HostHeader" -Value "newname.example.com"
# Change the port on an existing binding
Set-WebBinding -Name "Site2" -BindingInformation "*:80:site2.example.com" -PropertyName "BindingInformation" -Value "*:8080:site2.example.com"
Port-Based Hosting
Port-based hosting is simpler — each site listens on a different port. No host header is required. This approach is appropriate for development servers or internal administrative tools where users can be directed to specific ports:
New-WebSite -Name "AdminSite" -PhysicalPath "C:inetpubadmin" -Port 8080 -IPAddress "*"
New-WebSite -Name "ApiSite" -PhysicalPath "C:inetpubapi" -Port 8081 -IPAddress "*"
New-WebSite -Name "DevSite" -PhysicalPath "C:inetpubdev" -Port 8082 -IPAddress "*"
Remember to open the appropriate firewall ports:
New-NetFirewallRule -DisplayName "IIS Port 8080" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow
New-NetFirewallRule -DisplayName "IIS Port 8081" -Direction Inbound -Protocol TCP -LocalPort 8081 -Action Allow
New-NetFirewallRule -DisplayName "IIS Port 8082" -Direction Inbound -Protocol TCP -LocalPort 8082 -Action Allow
IP-Based Hosting
For IP-based hosting, your server needs multiple IP addresses assigned to a network adapter. Add additional IPs in Windows network settings, then bind each IIS site to a specific IP:
# Add a secondary IP to a network adapter (example)
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress "192.168.1.11" -PrefixLength 24
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress "192.168.1.12" -PrefixLength 24
# Create sites bound to specific IPs (no host header needed)
New-WebSite -Name "IPSite1" -PhysicalPath "C:inetpubipsite1" -Port 80 -IPAddress "192.168.1.11"
New-WebSite -Name "IPSite2" -PhysicalPath "C:inetpubipsite2" -Port 80 -IPAddress "192.168.1.12"
With IP-based bindings, the host header is not checked — any request arriving on that IP and port is routed to that site regardless of what Host header the client sends.
Wildcard Bindings
IIS supports wildcard host headers, allowing a single site to respond to all subdomains of a domain. This is useful for wildcard subdomain applications (like multi-tenant SaaS platforms):
# Wildcard binding for *.example.com
New-WebBinding -Name "WildcardSite" -Protocol "http" -Port 80 -HostHeader "*.example.com" -IPAddress "*"
The wildcard only matches one subdomain level deep. *.example.com matches foo.example.com but not sub.foo.example.com. For the wildcard to work, DNS must also be configured with a wildcard A record (*.example.com → server IP).
Managing Multiple Sites with PowerShell
Use PowerShell to enumerate and manage all sites efficiently:
# List all sites with state, physical path, and bindings
Get-WebSite | Select-Object Name, State, PhysicalPath, @{N="Bindings";E={($_.bindings.collection | ForEach-Object { $_.bindingInformation }) -join ", "}}
# Stop all sites except one
Get-WebSite | Where-Object { $_.Name -ne "ProductionSite" } | ForEach-Object { Stop-WebSite -Name $_.Name }
# Restart all running sites
Get-WebSite | Where-Object { $_.State -eq "Started" } | ForEach-Object { Restart-WebSite -Name $_.Name }
# Export all site configurations to a file
Get-WebSite | ConvertTo-Json -Depth 5 | Out-File "C:iis-site-export.json"
Testing Site Bindings with the Hosts File
Before DNS is configured, test host-header bindings by adding entries to the Windows hosts file on your test machine. The hosts file is located at C:WindowsSystem32driversetchosts. Edit it as Administrator:
# Add to C:WindowsSystem32driversetchosts on the client machine:
192.168.1.10 site1.example.com
192.168.1.10 www.site1.example.com
192.168.1.10 site2.example.com
192.168.1.10 site3.example.com
After saving, test each site from the browser or with PowerShell:
Invoke-WebRequest -Uri "http://site1.example.com" -UseBasicParsing | Select-Object StatusCode, Content
Invoke-WebRequest -Uri "http://site2.example.com" -UseBasicParsing | Select-Object StatusCode, Content
Site-Specific Application Pools and Site Isolation
Proper isolation between sites is critical in a shared hosting environment. Each site should run in its own application pool so that a crash, memory leak, or compromise in one site does not affect others. The application pool isolation model in IIS means each site’s worker process (w3wp.exe) runs under a different identity with access only to its own content.
# Verify each site has its own application pool
Get-WebSite | Select-Object Name, applicationPool
# Ensure no two sites share an application pool in a security-sensitive environment
$poolUsage = Get-WebSite | Group-Object applicationPool | Where-Object { $_.Count -gt 1 }
if ($poolUsage) {
Write-Warning "The following application pools are shared between sites:"
$poolUsage | ForEach-Object { Write-Warning "Pool: $($_.Name) - Sites: $(($_.Group.Name) -join ', ')" }
}
Additionally, configure NTFS permissions so each app pool identity can only read its own site’s content. Never give IIS_IUSRS broad access to C:inetpub — always grant the specific virtual account per pool.
For maximum isolation, configure application pools to recycle on a schedule and set CPU limits to prevent any one site from monopolizing server resources:
# Set CPU limit to 25% for a pool
Set-ItemProperty -Path "IIS:AppPoolsSite1Pool" -Name "cpu.limit" -Value 25000
Set-ItemProperty -Path "IIS:AppPoolsSite1Pool" -Name "cpu.action" -Value "KillW3wp"
# Set memory limit (private bytes, in KB, 500MB = 512000)
Set-ItemProperty -Path "IIS:AppPoolsSite1Pool" -Name "recycling.periodicRestart.privateMemory" -Value 512000
With host headers, port-based, and IP-based approaches — plus proper application pool isolation and thorough PowerShell management — IIS on Windows Server 2022 can efficiently serve dozens or hundreds of websites from a single server with strong boundaries between them.