Public/Install-Solr.ps1
#Set-StrictMode -Version Latest ##################################################### # Install-Solr ##################################################### <#PSScriptInfo .VERSION 0.0 .GUID 602bc07e-a621-4738-8c27-0edf4a4cea8e .AUTHOR David Walker, Sitecore Dave, Radical Dave .COMPANYNAME David Walker, Sitecore Dave, Radical Dave .COPYRIGHT David Walker, Sitecore Dave, Radical Dave .TAGS sitecore powershell local install iis solr .LICENSEURI https://github.com/SitecoreDave/SharedSitecore.SitecoreLocal/blob/main/LICENSE .PROJECTURI https://github.com/SitecoreDave/SharedSitecore.SitecoreLocal .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .SYNOPSIS @@synoposis@@ .DESCRIPTION @@description@@ .EXAMPLE PS> .\Install-Solr 'name' .EXAMPLE PS> .\Install-Solr 'name' 'template' .EXAMPLE PS> .\Install-Solr 'name' 'template' 'd:\repos' .EXAMPLE PS> .\Install-Solr 'name' 'template' 'd:\repos' -Persist User .Link https://github.com/SitecoreDave/SharedSitecore.SitecoreLocal # Credit primarily to jermdavis for the original script # and https://gitlab.com/viet.hoang/workshop/blob/master/Scripts%20for%20Sitecore%209.1/helper.psm1 .OUTPUTS System.String #> Function Install-Solr { [CmdletBinding(SupportsShouldProcess,PositionalBinding=$true)] Param( [string]$solrVersion = "8.4.0", [string]$installFolder = "", [string]$solrPort = "8840", [string]$solrHost = "localhost", [bool]$solrSSL = $TRUE, [string]$nssmVersion = "2.24", [string]$keystoreSecret = "secret", [string]$KeystoreFile = 'solr-ssl.keystore.jks', [string]$SolrDomain = 'localhost', [string]$maxJvmMem = '512m', [string]$downloadFolder = '', [switch]$Clobber ) [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Turning off progress bar to (greatly) speed up installation $Global:ProgressPreference = "SilentlyContinue" $ErrorActionPreference = 'Stop' $VerbosePreference = "SilentlyContinue" Write-Host 'boom' $PSScriptName = ($MyInvocation.MyCommand.Name.Replace(".ps1","")) Write-Verbose (Get-Parameters $MyInvocation.MyCommand.Parameters $PSBoundParameters -Message "$($PSScriptName):start" -Show -Stamp).output if (!$installFolder){ $root = if (Get-PSDrive 'd' -ErrorAction SilentlyContinue) { 'd' } else { 'c' } $installfolder = "$($root):\solr" } $solrName = "solr-$solrVersion" $solrRoot = "$installFolder\$solrName" $nssmRoot = "$installFolder\nssm-$nssmVersion" $solrPackage = "http://archive.apache.org/dist/lucene/solr/$solrVersion/$solrName.zip" $nssmPackage = "http://nssm.cc/release/nssm-$nssmVersion.zip" $ConfigurationFile = "$MyInvocation.MyCommand.Name.parameters.json" if ((Test-Path "$ConfigurationFile.user")) { $ConfigurationFile = "$ConfigurationFile.user" } Write-Host "configurationFile:$configurationFile" if ((Test-Path $ConfigurationFile)) { $config = Get-Content -Raw $ConfigurationFile | ConvertFrom-Json if ($config) { if ($config.SolrVersion) { $solrVersion = $config.solrVersion } if ($config.installFolder) { $installFolder = $config.installFolder } if ($config.solrPort) { $solrPort = $config.solrPort } if ($config.solrHost) { $solrHost = $config.solrHost } if ($config.solrSSL) { $solrSSL = $config.solrSSL } if ($config.nssmVersion) { $nssmVerion = $config.nssmVersion } if ($config.keystoreSecret) { $keystoreSecret = $config.keystoreSecret } if ($config.keystoreFile) { $KeystoreFile = $config.keystoreFile } if ($config.solrDomain) { $SolrDomain = $config.solrDomain } if ($config.maxJvmMem) { $maxJvmMem = $config.maxJvmMem } if ($config.clobber) { $Clobber = $config.clobber } } } $solrRoot = "$installFolder\$solrName" if (Test-Path $solrRoot) { if (!$Clobber) { $results = "$solrRoot already exists! Must use -Clobber to reinstall." Write-Verbose (Get-Parameters $MyInvocation.MyCommand.Parameters $PSBoundParameters -Message "$($PSScriptName):$results" -Show -Stamp).output return } else { Remove-Item $solrRoot -Recurse } } #if(!$downloadFolder) { $downloadFolder = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("..\assets") } #if(!$downloadFolder) { $downloadFolder = Join-Path (Split-Path (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent) -Parent) "assets" } #Write-Verbose "downloadFolder:$downloadFolder" #if (!(Test-Path $downloadFolder)){ # New-Item -ItemType Directory -Path $downloadFolder #} ## Verify elevated ## https://superuser.com/questions/749243/detect-if-powershell-is-running-as-administrator $elevated = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544") if(!($elevated)) { throw "In order to install services, please run this script elevated." } $JavaMinVersionRequired = "8.0.1510" if (Get-Module("JavaHelpers")) { Remove-Module "JavaHelpers" } Import-Module "$PSScriptRoot\JavaHelpers.psm1" $ErrorActionPreference = 'Stop' $JREVersion = "" $javaPath = "C:\Program Files\Java" if (Test-Path $javaPath) { $JREVersion = Get-ChildItem -Path $javaPath -name | Where-Object { -not $_.PsIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -first 1 } if (!$JREVersion) { #choco install javaruntime $javaInstallPath = Join-Path $javaPath $JREVersion #$javaUrl = (Invoke-WebRequest -UseBasicParsing https://www.java.com/en/download/manual.jsp).Content | ForEach-Object{[regex]::matches($_, '(?:<a title="Download Java software for Windows \(64-bit\)" href=")(.*)(?:">)').Groups[1].Value} $JDK_VER="7u75" $JDK_FULL_VER="7u75-b05" #$JDK_PATH="1.7.0_75" $javaUrl = "http://download.oracle.com/otn-pub/java/jdk/$JDK_FULL_VER/jdk-$JDK_VER-windows-x64.exe" #Java='https://javadl.oracle.com/webapps/download/AutoDL?BundleId=244068_89d678f2be164786b292527658ca1605' $JDK_VER="8u202" $JDK_FULL_VER="8u202-b08" $JDK_PATH="1.8.0_60" $JDK_URL_PATH = "1961070e4c9b4e26a04e7f5a083f551e" $javaUrl = "https://download.oracle.com/otn/java/jdk/$JDK_FULL_VER/$JDK_URL_PATH/jdk-$JDK_VER-windows-x64.exe" Write-Verbose "javaUrl:$javaUrl" Install-Tool java $javaUrl $javaInstallPath -packages $downloadFolder # would require creating Install-Java: -JavaMinVersionRequired $JavaMinVersionRequired if (Test-Path $javaPath) { $JREVersion = Get-ChildItem -Path $javaPath -name | Where-Object { -not $_.PsIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -first 1 -ErrorAction SilentlyContinue } } if (!$JREVersion) { Write-Error "$PSScriptName ERROR:Java not installed" exit 1 } #Invoke-WebRequest -UseBasicParsing -OutFile jre8.exe $URL #Start-Process .\jre8.exe '/s REBOOT=0 SPONSORS=0 AUTO_UPDATE=0' -wait # Ensure Java environment variable try { $keytool = (Get-Command 'keytool.exe').Source } catch { $keytool = Get-JavaKeytool -JavaMinVersionRequired $JavaMinVersionRequired } if (!$keytool) { $jrePaths = @('C:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\bin') Write-Host "Checking all the paths..." foreach($jrePath in $jrePaths) { $testPath = Join-Path "$jrePath" 'keytool.exe' Write-Host "testPath:$testPath" if (Test-Path $testPath) { $keytool = (Get-Command $testPath).Source } } } if (!$keytool) { Write-Host "no keytool found"; exit 1 } #Write-Host "keytool:$keytool" # download & extract the solr archive to the right folder #$solrZip = "$downloadFolder\$solrName.zip" Install-Tool $solrPackage solr -path $solrRoot -packages $downloadFolder # download & extract the nssm archive to the right folder #$nssmZip = "$downloadFolder\nssm-$nssmVersion.zip" Install-Tool $nssmPackage nssm -path $nssmRoot -packages $installFolder ### PARAM VALIDATION if($keystoreSecret -ne 'secret') { Write-Error 'The keystore password must be "secret", because Solr apparently ignores the parameter' } if((Test-Path $KeystoreFile)) { if($Clobber) { Write-Host "Removing $KeystoreFile..." Remove-Item $KeystoreFile } else { $KeystorePath = Resolve-Path $KeystoreFile Write-Warning "Keystore file $KeystorePath already existed. To regenerate it, pass -Clobber." } } $P12Path = [IO.Path]::ChangeExtension($KeystoreFile, 'p12') if((Test-Path $P12Path)) { if($Clobber) { Write-Host "Removing $P12Path..." Remove-Item $P12Path } else { $P12Path = Resolve-Path $P12Path Write-Warning "Keystore file $P12Path already existed. To regenerate it, pass -Clobber." } } ### DOING STUFF if(!(Test-Path $KeystoreFile)) { Write-Host '' Write-Host 'Generating JKS keystore...' & $keytool -genkeypair -alias solr-ssl -keyalg RSA -keysize 2048 -keypass $keystoreSecret -storepass $keystoreSecret -validity 9999 -keystore $KeystoreFile -ext SAN=DNS:$SolrDomain,IP:127.0.0.1 -dname "CN=$SolrDomain, OU=Organizational Unit, O=Organization, L=Location, ST=State, C=Country" Write-Host '' Write-Host 'Generating .p12 to import to Windows...' & $keytool -importkeystore -srckeystore $KeystoreFile -destkeystore $P12Path -srcstoretype jks -deststoretype pkcs12 -srcstorepass $keystoreSecret -deststorepass $keystoreSecret Write-Host '' Write-Host 'Trusting generated SSL certificate...' $secureStringKeystorePassword = ConvertTo-SecureString -String $keystoreSecret -Force -AsPlainText $root = Import-PfxCertificate -FilePath $P12Path -Password $secureStringKeystorePassword -CertStoreLocation Cert:\LocalMachine\Root Write-Host 'SSL certificate is now locally trusted. (added as root CA)' if(-not $KeystoreFile.EndsWith('solr-ssl.keystore.jks')) { Write-Warning 'Your keystore file is not named "solr-ssl.keystore.jks"' Write-Warning 'Solr requires this exact name, so make sure to rename it before use.' } $KeystorePath = Resolve-Path $KeystoreFile Copy-Item $KeystorePath -Destination "$solrRoot\server\etc\solr-ssl.keystore.jks" -Force } # Update solr cfg to use keystore & right host name if(Test-Path -Path "$solrRoot\bin\solr.in.cmd.old") { Write-Host "Resetting solr.in.cmd" -ForegroundColor Green Remove-Item "$solrRoot\bin\solr.in.cmd" Rename-Item -Path "$solrRoot\bin\solr.in.cmd.old" -NewName "$solrRoot\bin\solr.in.cmd" } Write-Host "Rewriting solr config" $cfg = Get-Content "$solrRoot\bin\solr.in.cmd" Rename-Item "$solrRoot\bin\solr.in.cmd" "$solrRoot\bin\solr.in.cmd.old" $certStorePath = "etc/solr-ssl.keystore.jks" $newCfg = $cfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_KEY_STORE=$certStorePath" } $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_KEY_STORE_PASSWORD=secret", "set SOLR_SSL_KEY_STORE_PASSWORD=$keystoreSecret" } $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_TRUST_STORE=$certStorePath" } $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_SSL_TRUST_STORE_PASSWORD=secret", "set SOLR_SSL_TRUST_STORE_PASSWORD=$keystoreSecret" } $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_HOST=192.168.1.1", "set SOLR_HOST=$solrHost" } $newCfg = $newCfg | ForEach-Object { $_ -replace "REM set SOLR_JAVA_MEM=-Xms512m -Xmx512m", "set SOLR_JAVA_MEM=-Xms512m -Xmx$maxJvmMem" } $newCfg | Set-Content "$solrRoot\bin\solr.in.cmd" # install the service & runs $svc = Get-Service "$solrName" -ErrorAction SilentlyContinue if ($svc) { Write-Host "Solr service $solrName already exists..." if ($Clobber) { Write-Host "Removing Solr service" &"$installFolder\nssm-$nssmVersion\win64\nssm.exe" remove "$solrName" $svc = Get-Service "$solrName" -ErrorAction SilentlyContinue } } if(!($svc)) { Write-Host "Installing Solr service:$solrName" &"$installFolder\nssm-$nssmVersion\win64\nssm.exe" install "$solrName" "$solrRoot\bin\solr.cmd" "-f" "-p $solrPort" $svc = Get-Service "$solrName" -ErrorAction SilentlyContinue } if($svc.Status -ne "Running") { Write-Host "Starting Solr service:$($solrName):$solrPort..." Start-Service "$solrName" } elseif ($svc.Status -eq "Running") { Write-Host "Restarting Solr service$($solrName):$solrPort..." Restart-Service "$solrName" } Start-Sleep -s 5 # finally prove it's all working $protocol = "http" if($solrSSL) { $protocol = "https" } Invoke-Expression "start $($protocol)://$($solrHost):$solrPort/solr/#/" # Resetting Progress Bar back to default $Global:ProgressPreference = "Continue" Write-Host '' Write-Host 'Done!' -InformationVariable results -ForegroundColor Green Write-Verbose (Get-Parameters $MyInvocation.MyCommand.Parameters $PSBoundParameters -Message "$($PSScriptName):$results" -Show -Stamp).output } |