This guide covers recommended layout, IIS steps, and a PowerShell script to automate setup.
Best practice folder layout
• Create one folder per site outside wwwroot.
• Example:
– C:\inetpub\MyNewSite
Step by step in IIS Manager GUI
1) Create the site folder
– Example: C:\inetpub\MyNewSite
– Place site files inside this folder.
2) Create a dedicated Application Pool
– IIS Manager -> Application Pools -> Add Application Pool
– Name: MyNewSiteAppPool
– .NET CLR: use the required runtime or No Managed Code for static sites
– Pipeline: Integrated
3) Set NTFS permissions on the site folder
– Grant Modify to the App Pool identity only: IIS AppPool
– Remove unnecessary write permissions for Users or Everyone.
4) Add the website
– IIS Manager -> Sites -> Add Website
– Site name: MyNewSite
– Application pool: MyNewSiteAppPool
– Physical path: C:\inetpub\MyNewSite
– Binding: http on port 80 with a host name, for example mynewsite.local
5) Add HTTPS (optional here, see the separate certificate guide)
– Add an https binding and select a certificate when available.
6) Test locally
– Add a hosts file entry for testing: 127.0.0.1 mynewsite.local
– Browse to http://mynewsite.local or https://mynewsite.local
PowerShell script to create folder, app pool, site, and permissions
Run in an elevated PowerShell session.
# Variables
$SiteName = "MyNewSite"
$AppPool = "MyNewSiteAppPool"
$PhysicalPath = "C:\inetpub\MyNewSite"
$HttpHost = "mynewsite.local"
$HttpPort = 80
Import-Module WebAdministration
# 1) Create folder if it does not exist
if (-not (Test-Path -LiteralPath $PhysicalPath)) {
New-Item -ItemType Directory -Path $PhysicalPath | Out-Null
}
# 2) Create a dedicated Application Pool
if (-not (Test-Path IIS:\AppPools\$AppPool)) {
New-WebAppPool -Name $AppPool | Out-Null
# Set defaults as needed
Set-ItemProperty "IIS:\AppPools\$AppPool" -Name "managedPipelineMode" -Value "Integrated"
# Use No Managed Code for static sites
# Set-ItemProperty "IIS:\AppPools\$AppPool" -Name "managedRuntimeVersion" -Value ""
}
# 3) Grant NTFS permissions to the App Pool identity
# Grant Modify to IIS AppPool\$AppPool on the site folder recursively
$aclCmd = 'icacls "{0}" /grant "IIS AppPool\{1}:(OI)(CI)(M)" /T' -f $PhysicalPath, $AppPool
cmd.exe /c $aclCmd
# 4) Create the website and bind HTTP
if (-not (Get-Website -Name $SiteName -ErrorAction SilentlyContinue)) {
New-Website -Name $SiteName -PhysicalPath $PhysicalPath -Port $HttpPort -HostHeader $HttpHost -ApplicationPool $AppPool | Out-Null
} else {
# Ensure binding exists
if (-not (Get-WebBinding -Name $SiteName -Protocol "http" -ErrorAction SilentlyContinue | Where-Object { $_.bindingInformation -match ":$HttpPort:$HttpHost" })) {
New-WebBinding -Name $SiteName -Protocol "http" -Port $HttpPort -HostHeader $HttpHost | Out-Null
}
}
Write-Host "Site '$SiteName' created and bound to http://$HttpHost:$HttpPort"
Optional: create a self-signed cert and add HTTPS binding
For a quick internal test, you can generate a self-signed certificate and bind it.
$HttpsPort = 443
$DnsName = $HttpHost # reuse hostname
# Create the self-signed certificate in LocalMachine\My
$cert = New-SelfSignedCertificate -DnsName $DnsName -CertStoreLocation "cert:\LocalMachine\My" -FriendlyName "$SiteName SelfSigned" -KeyLength 2048 -HashAlgorithm sha256 -KeyExportPolicy Exportable -NotAfter (Get-Date).AddYears(1)
# Add the HTTPS binding with SNI
if (-not (Get-WebBinding -Name $SiteName -Protocol "https" -ErrorAction SilentlyContinue | Where-Object { $_.bindingInformation -match ":$HttpsPort:$DnsName" })) {
New-WebBinding -Name $SiteName -Protocol "https" -Port $HttpsPort -HostHeader $DnsName | Out-Null
}
# Attach the certificate to the SNI binding
$bindingPath = "IIS:\SslBindings.0.0.0!$HttpsPort!$DnsName"
if (-not (Test-Path $bindingPath)) {
New-Item $bindingPath -Thumbprint $cert.Thumbprint -SSLFlags 1 | Out-Null
} else {
Set-Item -Path $bindingPath -Thumbprint $cert.Thumbprint -SSLFlags 1
}
Write-Host "HTTPS binding added for https://$DnsName:$HttpsPort using a self-signed certificate."
Notes
• Run PowerShell as Administrator.
• For production, use a trusted CA certificate. Self-signed will show browser warnings.
• Keep one site per Application Pool for better isolation.