-
-
Save NickCraver/6b5e75c153d60d0df5b0970d52412d4e to your computer and use it in GitHub Desktop.
Register-Websites.psm1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
This script will set up sites in IIS, pointing them at their respective directories on your machine. | |
By convention, the site name, host name and application pool name are all the same. For example, local.careers.stackoverflow.com. | |
It will also update the hosts file to point host names to 127.0.0.1 (localhost) | |
Prerequisites: | |
- IIS is already installed, including ASP.Net 4.5 | |
Troubleshooting: | |
- Out-File : The process cannot access the file 'C:\Windows\System32\drivers\etc\hosts' because it is being used by another process | |
- Try to re-run the script several times. Try to end the explorer.exe task and re-run the script. If nothing works, reboot and try again. | |
Example Websites config: | |
@( | |
@{ | |
Directory = "StackOverflow\StackOverflow"; | |
Site = "local.mse.com"; | |
Aliases = "discuss.local.area51.lse.com"; | |
Databases = "StackExchange.Meta", "Area51.Meta"; | |
}, | |
@{ | |
Directory = "StackOverflow\StackExchange.Website"; | |
Site = "local.lse.com"; | |
Databases = "StackExchange"; | |
}, | |
@{ | |
Directory = "StackOverflow\StackAuth"; | |
Site = "local.stackauth.com"; | |
Databases = "Sites"; | |
}, | |
@{ | |
Directory = "StackOverflow\StackOverflow.Api.V2"; | |
Site = "api.local.lse.com"; | |
}, | |
@{ | |
Directory = "Area51\StackOverflow.Proposals"; | |
Site = "local.area51.lse.com"; | |
Databases = "Area51"; | |
} | |
) | |
#> | |
function Register-Websites { | |
Param( | |
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] $Websites | |
) | |
Write-Host "Registering IIS Websites..." -ForegroundColor "Magenta" | |
# Grab the web admin and HOSTS module | |
Import-Module WebAdministration | |
# DLL blocking on Windows, yay fun! | |
Get-ChildItem "$PSScriptRoot\Includes\PsHosts" | Unblock-File | |
Import-Module "$PSScriptRoot\Includes\PsHosts" | |
# Unlock the serverRuntime section of system.webServer. | |
Set-WebConfiguration "//system.WebServer/serverRuntime" "machine/webroot/apphost" -Metadata overrideMode -Value Allow | |
# Set some common variables | |
Set-WebConfigurationProperty "/system.webServer/httpCompression/scheme[@name='gzip']" -PSPath IIS:\ -name dynamicCompressionLevel -value 4 | |
# Remove default website and application pool - we don't want it for any setups | |
Get-Website -Name "Default Web Site" | Remove-Website | |
# Remove DefaultAppPool app pool | |
if (Test-Path "IIS:\AppPools\DefaultAppPool") | |
{ | |
Remove-WebAppPool -Name "DefaultAppPool" | |
} | |
# First, check for existence of all folders | |
$missing = $false | |
foreach ($website in $Websites) { | |
$webPath = Join-Path $Env:CODEROOT $website.Directory | |
if (!(Test-Path $webPath)) | |
{ | |
$missing = $true | |
Write-Error "Could not find folder $webPath" | |
Write-Error "" | |
} | |
} | |
# Let's not fail partially; go get everything | |
if ($missing -eq $true) { | |
Write-Warning "Go back and run the repos step." | |
Write-Warning "" | |
return | |
} | |
$iis_iusrs = New-Object System.Security.Principal.NTAccount BUILTIN\IIS_IUSRS | |
$acl_iis_iusrs = Get-AccessRule $iis_iusrs | |
# Remove & create sites in IIS | |
foreach ($website in $Websites) { | |
$baseHost = $website.Site | |
Write-Host "Creating IIS Website & AppPool for $baseHost..." -ForegroundColor "Magenta" | |
# Host name, site name and app pool name are identical by convention | |
$rootPath = Join-Path $env:CODEROOT $website.Directory | |
Write-Host " Website directory: $rootPath" | |
$acl = Get-Acl $rootPath | |
if (!(Find-AccessRule $acl $iis_iusrs)) { | |
Write-Host " Granting access to $rootPath for IIS_IUSRS" | |
$acl.AddAccessRule($acl_iis_iusrs) | |
Set-Acl $rootPath $acl | |
} | |
# Remove Existing site and pool | |
Get-Website -Name $baseHost | Remove-Website | |
if (Test-Path "IIS:\AppPools\$baseHost") | |
{ | |
Remove-WebAppPool -Name $baseHost | |
} | |
Write-Host " Creating AppPool for $baseHost" | |
$appPool = New-WebAppPool -Name $baseHost | |
$appPool | Set-ItemProperty -Name ProcessModel.loadUserProfile -Value false | |
$appPool | Set-ItemProperty -Name managedRuntimeVersion -Value v4.0 | |
# Create new site | |
Write-Host " Creating Website for $baseHost" | |
$iisWebsite = New-WebSite -Name $baseHost -ApplicationPool $baseHost -PhysicalPath $rootPath -HostHeader $baseHost | |
# Add hosts file entry | |
Write-Host " Creating HOSTS entry for $baseHost to 127.0.0.1" | |
Get-HostEntry | Where { $_.Name -eq $baseHost } | Remove-HostEntry | |
Add-HostEntry -Name $baseHost -Address 127.0.0.1 -Comment "auto-generated by dev-local-setup" | Out-Null | |
# If requested, SSL self-signed certs | |
if ($website.Certificate) | |
{ | |
New-IISSelfSignedCertificate $baseHost $baseHost | |
} | |
foreach ($hostAlias in $website.Aliases) { | |
Write-Host " Alias: Creating HOSTS entry for $hostAlias to 127.0.0.1" | |
Get-HostEntry | Where { $_.Name -eq $hostAlias } | Remove-HostEntry | |
Add-HostEntry -Name $hostAlias -Address 127.0.0.1 -Comment "auto-generated by dev-local-setup" | Out-Null | |
Write-Host " Alias: Adding website binding for $hostAlias" | |
New-WebBinding -Name $baseHost -IPAddress "*" -Port 80 -HostHeader $hostAlias | |
if ($website.Certificate) | |
{ | |
# Need to add a cert for each... | |
New-IISSelfSignedCertificate $baseHost $hostAlias | |
} | |
} | |
Write-Host "IIS Website & AppPool for $baseHost created." -ForegroundColor "Green" | |
} | |
Write-Host "IIS Websites registered." -ForegroundColor "Green" | |
} | |
function Find-AccessRule ($acl, $account) { | |
foreach ($item in $acl.Access) { | |
if ($item.IdentityReference -eq $account) { | |
return $item | |
} | |
} | |
} | |
function Get-AccessRule ($account) { | |
New-Object System.Security.AccessControl.FileSystemAccessRule ($account, | |
[System.Security.AccessControl.FileSystemRights]::Read, | |
([System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit), | |
[System.Security.AccessControl.PropagationFlags]::None, | |
[System.Security.AccessControl.AccessControlType]::Allow) | |
} | |
function New-IISSelfSignedCertificate ($baseHost, $host) { | |
Write-Host " SSL Certificate requested. Creating self-signed cert for $host." | |
# Recreate self-signed SSL cert | |
Push-Location cert:\LocalMachine\My | |
Get-ChildItem -DnsName $host | Remove-Item | |
$cert = New-SelfSignedCertificate -DnsName $host | |
Pop-Location | |
# Re-add it to the Root store (needed for the green padlock) | |
Push-Location cert:\LocalMachine\Root | |
Get-ChildItem -DnsName $host | Remove-Item | |
$rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList Root, LocalMachine | |
$rootStore.Open("MaxAllowed") | |
$rootStore.Add($cert) | |
$rootStore.Close() | |
Pop-Location | |
Write-Host " SSL Certificate added to local root store." | |
Write-Host " Removing any existing WebBindings for $host..." -NoNewline | |
Get-WebBinding -Name $baseHost -Protocol 'https' -Port 443 -HostHeader $host | Remove-WebBinding | |
Write-Host "removed." | |
# Recreate SSL bindings | |
Write-Host " Adding a new WebBinding for $host..." -NoNewline | |
New-WebBinding -Name $baseHost -Protocol 'https' -Port 443 -HostHeader $host -SslFlags 1 # SNI enabled w/o IIS Central Cert Store | |
Write-Host "added." | |
# Required for SNI | |
$existsCheck = netsh http show sslcert hostnameport=$host:443 | |
if ($existsCheck -Like "*$host:443*") { | |
Write-Host " Existing netsh sslcert found for $host, removing..." -NoNewline | |
netsh http delete sslcert hostnameport=$($host):443 | |
} | |
Write-Host " Adding netsh sslcert binding..." -NoNewline | |
netsh http add sslcert hostnameport=$($host):443 certhash=$($cert.Thumbprint) appid='{00000000-0000-0000-0000-000000000000}' certstorename=MY | |
Write-Host " SNI thumbprint added." | |
Write-Host " SSL Certificate setup complete." | |
Write-Host "" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Half my host entries were giving me:
I ended up simplifying those two spots to use
Set-HostEntry
and the issue seems to have gone away.