Remotely/Utilities/Install-RemotelyServer.ps1
2021-07-29 07:56:09 -07:00

406 lines
14 KiB
PowerShell

<#
.SYNOPSIS
Configures IIS and installs the Remotely server.
.COPYRIGHT
Copyright © 2020 Translucency Software. All rights reserved.
#>
param (
# The name to use for the IIS Application Pool for the Remotely site.
[Parameter(Mandatory=$True)]
[string]$AppPoolName,
# The name to use for the IIS site.
[Parameter(Mandatory=$True)]
[string]$SiteName,
# The folder path where the Remotely server files should be located.
[Parameter(Mandatory=$True)]
[string]$SitePath,
# The hostname that IIS will use for the site (e.g. remotely.mydomain.com).
[Parameter(Mandatory=$True)]
[string]$BindingHostname,
# Whether to run the script without any prompts.
[switch]$Quiet,
# The path to Windows ACME Simple (wacs.exe) to use for automatically obtaining and
# installing a Let's Encrypt certificate.
# (Project and downloads: https://github.com/win-acme/win-acme)
[string]$WacsPath,
# The email address to use when registering the certificate with WACS.
[string]$EmailAddress
)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ErrorActionPreference = "Stop"
$Host.UI.RawUI.WindowTitle = "Remotely Setup"
Clear-Host
#region Variables
$ServerCmdlets = $false
$FirewallSet = $false
$CopyErrors = $false
if ($PSScriptRoot -eq ""){
$PSScriptRoot = (Get-Location)
}
$Root = (Get-Item -Path $PSScriptRoot).Parent.FullName
#endregion
#region Functions
function Do-Pause {
if (!$Quiet){
pause
}
}
function Wrap-Host
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
# The text to write.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[String]
$Text,
# Param2 help description
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ConsoleColor]
$ForegroundColor
)
Begin
{
}
Process
{
if (!$Text){
Write-Host
return
}
$Width = $Host.UI.RawUI.BufferSize.Width
$SB = New-Object System.Text.StringBuilder
while ($Text.Length -gt $Width) {
[int]$LastSpace = $Text.Substring(0, $Width).LastIndexOf(" ")
$SB.AppendLine($Text.Substring(0, $LastSpace).Trim()) | Out-Null
$Text = $Text.Substring(($LastSpace), $Text.Length - $LastSpace).Trim()
}
$SB.Append($Text) | Out-Null
if ($ForegroundColor)
{
Write-Host $SB.ToString() -ForegroundColor $ForegroundColor
}
else
{
Write-Host $SB.ToString()
}
}
End
{
}
}
#endregion
#region Prerequisite Tests
### Test if process is elevated. ###
$User = [Security.Principal.WindowsIdentity]::GetCurrent()
if ((New-Object Security.Principal.WindowsPrincipal $User).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) -eq $false) {
Wrap-Host
Wrap-Host "Error: This installation needs to be run from an elevated process (Run as Administrator)." -ForegroundColor Red
Do-Pause
return
}
### Check PS version. ###
if ((Get-Host).Version.Major -lt 5) {
Wrap-Host
Wrap-Host "Error: PowerShell 5 is required. Please install it via the Windows Management Framework 5.1 download from Microsoft." -ForegroundColor Red
Do-Pause
return
}
### Check Script Root ###
if (!$PSScriptRoot) {
Wrap-Host
Wrap-Host "Error: Unable to determine working directory. Please make sure you're running the full script and not just a section." -ForegroundColor Red
Do-Pause
return
}
### Check OS version. ###
$OS = Get-WmiObject -Class Win32_OperatingSystem
if ($OS.Name.ToLower().Contains("home") -or $OS.Caption.ToLower().Contains("home")) {
Wrap-Host
Wrap-Host "Error: Windows Home version does not have the necessary features to run Remotely." -ForegroundColor Red
Do-Pause
return
}
### Test if Windows Feature cmdlets are available. ###
if ((Get-Command -Name "Add-WindowsFeature" -ErrorAction Ignore) -eq $null) {
$ServerCmdlets = $false
}
else {
$ServerCmdlets = $true
}
### Check if PostgreSQL is installed. ###
##if ((Get-Package -Name "*PostgreSQL*" -ErrorAction SilentlyContinue) -eq $null){
## Wrap-Host
## Wrap-Host "ERROR: PostgreSQL was not found. Please install it from https://postgresql.org." -ForegroundColor Red
## Wrap-Host
## Do-Pause
## return
##}
if ((Get-Package -Name "*3.1.2 - Windows Server Hosting*" -ErrorAction SilentlyContinue) -eq $null){
Wrap-Host "Downloading .NET Core Runtime and Hosting Bundle..."
$ProgressPreference = "SilentlyContinue"
Invoke-WebRequest -Uri "https://download.visualstudio.microsoft.com/download/pr/dd119832-dc46-4ccf-bc12-69e7bfa61b18/990843c6e0cbd97f9df68c94f6de6bb6/dotnet-hosting-3.1.2-win.exe" -OutFile "$env:TEMP\dotnet-hosting-3.1.2-win.exe"
$ProgressPreference = "Continue"
Start-Process -FilePath "$env:TEMP\dotnet-hosting-3.1.2-win.exe" -ArgumentList "/install /quiet /norestart" -Wait
Wrap-Host
Wrap-Host ".NET Runtime installation completed."
}
#endregion
### Hosting Requirements ###
Wrap-Host
Wrap-Host "**********************************"
Wrap-Host " IMPORTANT" -ForegroundColor Green
Wrap-Host "**********************************"
Wrap-Host
Wrap-Host "You must have the .NET Core Runtime installed, which includes the IIS hosting module. The SDK doesn't have this."
Wrap-Host
Wrap-Host "If you have not already done so, please download and install it from the following link:"
Wrap-Host
Wrap-Host "https://dotnet.microsoft.com/download"
Wrap-Host
Do-Pause
Clear-Host
### Intro ###
Clear-Host
Wrap-Host
Wrap-Host "**********************************"
Wrap-Host " Remotely Setup" -ForegroundColor Cyan
Wrap-Host "**********************************"
Wrap-Host
Wrap-Host "Hello, and thank you for trying out Remotely!" -ForegroundColor Green
Wrap-Host
Wrap-Host "This setup script will create an IIS site and install Remotely on this machine." -ForegroundColor Green
Wrap-Host
Wrap-Host "If you encounter any problems or have any questions, please contact Translucency_Software@outlook.com." -ForegroundColor Green
Wrap-Host
Do-Pause
Clear-Host
### Automatic IIS Setup ###
if ($ServerCmdlets) {
$RebootRequired = $false
Wrap-Host
Wrap-Host "Installing IIS components..." -ForegroundColor Green
Write-Progress -Activity "IIS Component Installation" -Status "Installing web server" -PercentComplete (1/7*100)
$Result = Add-WindowsFeature Web-Server
if ($Result.RestartNeeded -like "Yes")
{
$RebootRequired = $true
}
#Write-Progress -Activity "IIS Component Installation" -Status "Installing ASP.NET" -PercentComplete (2/7*100)
#$Result = Add-WindowsFeature Web-Asp-Net
#if ($Result.RestartNeeded -like "Yes")
#{
# $RebootRequired = $true
#}
#Write-Progress -Activity "IIS Component Installation" -Status "Installing ASP.NET 4.5" -PercentComplete (3/7*100)
#$Result = Add-WindowsFeature Web-Asp-Net45
#if ($Result.RestartNeeded -like "Yes")
#{
# $RebootRequired = $true
#}
#Write-Progress -Activity "IIS Component Installation" -Status "Installing web sockets" -PercentComplete (4/7*100)
#$Result = Add-WindowsFeature Web-WebSockets
#if ($Result.RestartNeeded -like "Yes")
#{
# $RebootRequired = $true
#}
Write-Progress -Activity "IIS Component Installation" -Status "Installing IIS management tools" -PercentComplete (5/7*100)
$Result = Add-WindowsFeature Web-Mgmt-Tools
if ($Result.RestartNeeded -like "Yes")
{
$RebootRequired = $true
}
#Write-Progress -Activity "IIS Component Installation" -Status "Installing web filtering" -PercentComplete (6/7*100)
#$Result = Add-WindowsFeature Web-Filtering
#if ($Result.RestartNeeded -like "Yes")
#{
# $RebootRequired = $true
#}
Write-Progress -Activity "IIS Component Installation" -Status "IIS setup completed" -PercentComplete (7/7*100) -Completed
Start-Sleep 2
}
else
{
Wrap-Host
Wrap-Host "Installing IIS components..." -ForegroundColor Green
Write-Progress -Activity "IIS Component Installation" -Status "Installing web server" -PercentComplete (1/7*100)
DISM /Online /Enable-Feature /FeatureName:IIS-WebServer /All /Quiet
#Write-Progress -Activity "IIS Component Installation" -Status "Installing ASP.NET" -PercentComplete (2/7*100)
#DISM /Online /Enable-Feature /FeatureName:IIS-ASPNET /All /Quiet
#Write-Progress -Activity "IIS Component Installation" -Status "Installing ASP.NET 4.5" -PercentComplete (3/7*100)
#DISM /Online /Enable-Feature /FeatureName:IIS-ASPNET45 /All /Quiet
#Write-Progress -Activity "IIS Component Installation" -Status "Installing web sockets" -PercentComplete (4/7*100)
#DISM /Online /Enable-Feature /FeatureName:IIS-WebSockets /All /Quiet
Write-Progress -Activity "IIS Component Installation" -Status "Installing IIS management tools" -PercentComplete (5/7*100)
DISM /Online /Enable-Feature /FeatureName:IIS-ManagementConsole /All /Quiet
#Write-Progress -Activity "IIS Component Installation" -Status "Installing web filtering" -PercentComplete (6/7*100)
#DISM /Online /Enable-Feature /FeatureName:IIS-RequestFiltering /All /Quiet
Write-Progress -Activity "IIS Component Installation" -Status "IIS setup completed" -PercentComplete (7/7*100) -Completed
Start-Sleep 2
}
Clear-Host
### Create IIS Site ##
[System.IO.Directory]::CreateDirectory($SitePath)
if ((Get-IISAppPool -Name $AppPoolName) -eq $null) {
New-WebAppPool -Name $AppPoolName
Set-ItemProperty -Path "IIS:\AppPools\$AppPoolName" -name processModel.identityType -Value 4
Set-ItemProperty -Path "IIS:\AppPools\$AppPoolName" -name processModel.loadUserProfile -Value $true
}
if ((Get-Website -Name $SiteName) -eq $null) {
New-Website -Name $SiteName -PhysicalPath $SitePath -HostHeader $BindingHostname -ApplicationPool $AppPoolName
}
Wrap-Host
Wrap-Host "This will DELETE ALL FILES in the selected website and install Remotely Server. If this is not your intention, close this window now and create a new website where Remotely Server will be installed." -ForegroundColor Red
Wrap-Host
Do-Pause
# Stop site.
Clear-Host
Wrap-Host
Wrap-Host "Stopping website..." -ForegroundColor Green
Stop-Website -Name $SiteName
### File Cleanup ###
Wrap-Host
Wrap-Host "Cleaning up existing files..." -ForegroundColor Green
$Success = $false
while ($Success -eq $false) {
try {
Get-ChildItem -Path "$SitePath" -Recurse | Remove-Item -Force -Recurse
$Success = $true
}
catch {
Start-Sleep -Seconds 1
}
}
### Download Server Package ###
try {
if ((Test-Path -Path "$env:TEMP\Remotely_Server_Win-x64.zip")){
Remove-Item -Path "$env:TEMP\Remotely_Server_Win-x64.zip" -Force
}
Wrap-Host "Downloading server package..."
$ProgressPreference = "SilentlyContinue"
Invoke-WebRequest -Uri "https://github.com/Jay-Rad/Remotely/releases/latest/download/Remotely_Server_Win-x64.zip" -OutFile "$env:TEMP\Remotely_Server_Win-x64.zip"
$ProgressPreference = "Continue"
Wrap-Host "Extracting server files..."
[System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
[System.IO.Compression.ZipFile]::ExtractToDirectory("$env:TEMP\Remotely_Server_Win-x64.zip", $SitePath)
}
catch {
Wrap-Host
Wrap-Host "Error: Unable to download or extract client files." -ForegroundColor Red
Do-Pause
return
}
### Set ACL on website folders and files ###
Wrap-Host
Wrap-Host "Setting ACLs..." -ForegroundColor Green
$Acl = Get-Acl -Path $SitePath
$Rule = New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\IIS_IUSRS", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")
$Acl.AddAccessRule($Rule)
$Acl.SetOwner((New-Object System.Security.Principal.NTAccount("Administrators")))
Set-Acl -Path $SitePath -AclObject $Acl
Get-ChildItem -Path $SitePath -Recurse | ForEach-Object {
Set-Acl -Path $_.FullName -AclObject $Acl
}
### Firewall Rules ###
Wrap-Host
Wrap-Host "Checking firewall rules for HTTP/HTTPS..." -ForegroundColor Green
try
{
Enable-NetFirewallRule -Name "IIS-WebServerRole-HTTP-In-TCP"
Enable-NetFirewallRule -Name "IIS-WebServerRole-HTTPS-In-TCP"
if ((Get-NetFirewallRule -Name "IIS-WebServerRole-HTTP-In-TCP").Enabled -like "False" -or (Get-NetFirewallRule -Name "IIS-WebServerRole-HTTP-In-TCP").Enabled -like "False")
{
$FirewallSet = $false
}
else
{
$FirewallSet = $true
}
}
catch
{
$FirewallSet = $false
}
# Start website.
Start-Website -Name $SiteName
### SSL certificate installation. ###
if ($WacsPath -ne $null -and (Test-Path -Path $WacsPath)) {
&"$WacsPath" --target iis --siteid (Get-Website -Name $SiteName).ID --installation iis --emailaddress $EmailAddress --accepttos
}
Wrap-Host
Wrap-Host
Wrap-Host
Wrap-Host "**********************************"
Wrap-Host " Server setup complete!" -ForegroundColor Green
Wrap-Host "**********************************"
Wrap-Host
Wrap-Host "If a path to Win-Acme exe path (WacsPath) wasn't provided, SSL/TLS needs to be set up in IIS. I recommend checking out Let's Encrypt for free, automated SSL certificates." -ForegroundColor Green
if ($RebootRequired) {
Wrap-Host
Wrap-Host "A reboot is required for the new IIS components to work properly. Please reboot your computer at your earliest convenience." -ForegroundColor Red
}
if ($FirewallSet -eq $false)
{
Wrap-Host
Wrap-Host "Firewall rules were not properly set. Please ensure that ports 80 (HTTP) and 443 (HTTPS) are open. Windows Firewall has predefined rules for these called ""World Wide Web Services (HTTP(S) Traffic-In)""." -ForegroundColor Red
}
if ($CopyErrors)
{
Wrap-Host
Wrap-Host "There were errors copying some of the server files. Please try deleting all files in the website directory and trying again." -ForegroundColor Red
}
Wrap-Host
Do-Pause