# ============================================================================ # 01 — Install prerequisites on Windows Server (Run as Administrator) # Target: Windows Server 2019/2022 with IIS # Usage: Run via RDP on VPS (103.124.94.58) # ============================================================================ #Requires -RunAsAdministrator $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' function Write-Step($msg) { Write-Host "" Write-Host "==========================================" -ForegroundColor Cyan Write-Host " $msg" -ForegroundColor Cyan Write-Host "==========================================" -ForegroundColor Cyan } function Test-CommandExists($cmd) { $null -ne (Get-Command $cmd -ErrorAction SilentlyContinue) } # --------------------------------------------------------------------------- Write-Step "1/7 — Enable IIS features" # --------------------------------------------------------------------------- $features = @( 'IIS-WebServerRole', 'IIS-WebServer', 'IIS-CommonHttpFeatures', 'IIS-HttpErrors', 'IIS-HttpRedirect', 'IIS-StaticContent', 'IIS-DefaultDocument', 'IIS-DirectoryBrowsing', 'IIS-ApplicationDevelopment', 'IIS-ISAPIExtensions', 'IIS-ISAPIFilter', 'IIS-Security', 'IIS-RequestFiltering', 'IIS-BasicAuthentication', 'IIS-WindowsAuthentication', 'IIS-HealthAndDiagnostics', 'IIS-HttpLogging', 'IIS-LoggingLibraries', 'IIS-Performance', 'IIS-HttpCompressionStatic', 'IIS-HttpCompressionDynamic', 'IIS-WebServerManagementTools', 'IIS-ManagementConsole', 'IIS-ManagementScriptingTools', 'IIS-WebSockets', 'NetFx4Extended-ASPNET45', 'IIS-ASPNET45', 'IIS-NetFxExtensibility45' ) foreach ($feature in $features) { $state = (Get-WindowsOptionalFeature -Online -FeatureName $feature -ErrorAction SilentlyContinue).State if ($state -ne 'Enabled') { Write-Host " Enabling $feature ..." -ForegroundColor Yellow Enable-WindowsOptionalFeature -Online -FeatureName $feature -NoRestart -ErrorAction SilentlyContinue | Out-Null } else { Write-Host " [OK] $feature" -ForegroundColor Green } } # --------------------------------------------------------------------------- Write-Step "2/7 — Install ASP.NET Core 10 Hosting Bundle" # --------------------------------------------------------------------------- if (Test-Path 'HKLM:\SOFTWARE\Microsoft\ASP.NET Core\Hosting Bundle\v10.0') { Write-Host " [OK] ASP.NET Core 10 Hosting Bundle already installed" -ForegroundColor Green } else { $url = 'https://builds.dotnet.microsoft.com/dotnet/Runtime/10.0.6/dotnet-hosting-10.0.6-win.exe' $exe = "$env:TEMP\dotnet-hosting-10.0.6-win.exe" Write-Host " Downloading $url ..." -ForegroundColor Yellow Invoke-WebRequest -Uri $url -OutFile $exe Write-Host " Installing (silent)..." -ForegroundColor Yellow Start-Process -FilePath $exe -ArgumentList '/quiet','/install','/norestart' -Wait Remove-Item $exe -Force Write-Host " [OK] ASP.NET Core 10 Hosting Bundle installed" -ForegroundColor Green } # --------------------------------------------------------------------------- Write-Step "3/7 — Install IIS URL Rewrite 2.1" # --------------------------------------------------------------------------- if (Test-Path 'HKLM:\SOFTWARE\Microsoft\IIS Extensions\URL Rewrite') { Write-Host " [OK] URL Rewrite already installed" -ForegroundColor Green } else { $url = 'https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi' $msi = "$env:TEMP\rewrite_amd64_en-US.msi" Write-Host " Downloading URL Rewrite ..." -ForegroundColor Yellow Invoke-WebRequest -Uri $url -OutFile $msi Start-Process msiexec.exe -ArgumentList "/i `"$msi`" /quiet /norestart" -Wait Remove-Item $msi -Force Write-Host " [OK] URL Rewrite installed" -ForegroundColor Green } # --------------------------------------------------------------------------- Write-Step "4/7 — Install .NET 10 SDK (for Gitea runner builds)" # --------------------------------------------------------------------------- if (Test-CommandExists 'dotnet') { $v = (dotnet --list-sdks) -match '^10\.' if ($v) { Write-Host " [OK] .NET 10 SDK installed" -ForegroundColor Green } } if (-not (Test-CommandExists 'dotnet') -or -not ((dotnet --list-sdks) -match '^10\.')) { $url = 'https://builds.dotnet.microsoft.com/dotnet/Sdk/10.0.104/dotnet-sdk-10.0.104-win-x64.exe' $exe = "$env:TEMP\dotnet-sdk-10.0.104-win-x64.exe" Write-Host " Downloading .NET 10 SDK ..." -ForegroundColor Yellow Invoke-WebRequest -Uri $url -OutFile $exe Start-Process $exe -ArgumentList '/quiet','/norestart' -Wait Remove-Item $exe -Force Write-Host " [OK] .NET 10 SDK installed" -ForegroundColor Green } # --------------------------------------------------------------------------- Write-Step "5/7 — Install Node.js 20 LTS" # --------------------------------------------------------------------------- if (Test-CommandExists 'node') { $nodeV = (node --version) -replace 'v', '' if ([version]$nodeV -ge [version]'20.0.0') { Write-Host " [OK] Node.js $nodeV installed" -ForegroundColor Green } } if (-not (Test-CommandExists 'node') -or ([version]((node --version) -replace 'v','')) -lt [version]'20.0.0') { $url = 'https://nodejs.org/dist/v20.18.0/node-v20.18.0-x64.msi' $msi = "$env:TEMP\node-v20.18.0-x64.msi" Write-Host " Downloading Node.js 20 ..." -ForegroundColor Yellow Invoke-WebRequest -Uri $url -OutFile $msi Start-Process msiexec.exe -ArgumentList "/i `"$msi`" /quiet /norestart" -Wait Remove-Item $msi -Force Write-Host " [OK] Node.js 20 installed" -ForegroundColor Green } # --------------------------------------------------------------------------- Write-Step "6/7 — Install Git for Windows" # --------------------------------------------------------------------------- if (Test-CommandExists 'git') { Write-Host " [OK] Git installed" -ForegroundColor Green } else { $url = 'https://github.com/git-for-windows/git/releases/download/v2.46.0.windows.1/Git-2.46.0-64-bit.exe' $exe = "$env:TEMP\Git-2.46.0-64-bit.exe" Write-Host " Downloading Git ..." -ForegroundColor Yellow Invoke-WebRequest -Uri $url -OutFile $exe Start-Process $exe -ArgumentList '/VERYSILENT','/NORESTART' -Wait Remove-Item $exe -Force Write-Host " [OK] Git installed" -ForegroundColor Green } # --------------------------------------------------------------------------- Write-Step "7/7 — Install win-acme (Let's Encrypt client)" # --------------------------------------------------------------------------- $wacsPath = 'C:\Tools\win-acme' if (Test-Path "$wacsPath\wacs.exe") { Write-Host " [OK] win-acme already installed at $wacsPath" -ForegroundColor Green } else { New-Item -ItemType Directory -Force -Path $wacsPath | Out-Null $url = 'https://github.com/win-acme/win-acme/releases/download/v2.2.9.1701/win-acme.v2.2.9.1701.x64.pluggable.zip' $zip = "$env:TEMP\wacs.zip" Write-Host " Downloading win-acme ..." -ForegroundColor Yellow Invoke-WebRequest -Uri $url -OutFile $zip Expand-Archive -Path $zip -DestinationPath $wacsPath -Force Remove-Item $zip -Force Write-Host " [OK] win-acme installed at $wacsPath\wacs.exe" -ForegroundColor Green } # --------------------------------------------------------------------------- Write-Host "" Write-Host "=========================================================" -ForegroundColor Green Write-Host " DONE — Prerequisites installed" -ForegroundColor Green Write-Host "=========================================================" -ForegroundColor Green Write-Host "" Write-Host "Next steps:" Write-Host " 1. Restart IIS: iisreset" Write-Host " 2. Run: .\scripts\deployment\02-setup-sqlserver.ps1" Write-Host " 3. Run: .\scripts\deployment\03-setup-iis-sites.ps1" Write-Host "" Write-Host "Refresh PATH in new PowerShell session to use dotnet/node/git"