Tom Dudfield Logo
Sitecore

Sitecore 9 and the Sitecore Installation Framework

Author

Tom Dudfield

Date Published

Sitecore 9 and the Sitecore Installation Framework

Prior to Sitecore 9, setting up an instance of Sitecore either relied on running the Sitecore installer or extracting a ZIP file and jumping through a few hoops. This process was simplified with the introduction of Sitecore Instance Manager but it was still tedious when configuring different server roles. I will show you how to setup a Sitecore 9 instance, while it is not completely straightforward it is a lot more flexible.

Sitecore 9 Requirements

Base

* IIS 10 (IIS 8.5 is supported but I would recommend moving away from it)

* Windows Server 2016 ideally 64-bit (2012 R2 is supported but best avoided to use IIS 10)

* .NET Framework 4.6.2 or newer

* Microsoft Visual C++ 2015 Redistributable

* Microsoft SQL Server 2016 SP1

* Solr 6.6.2 or an Azure Search instance (if you are deploying to Azure PaaS it is recommended to use the same search provider for development as your hosting platform)

For development

* Visual Studio 2017 for development

* Windows 10 or Windows Server 2016 ideally 64-bit (8.1 and 2012 R2 are supported but best avoided to use IIS 10)

* At a minimum a 4 core CPU and 16GB RAM, ideally an i7 and 32GB RAM

* At least a dual-monitor setup

* PowerShell 5.1 or newer

* Web Platform 5.0 Installer

SIF has the following dependencies

* WebAdministration Module

* Web Deploy 3.6 for Hosting Servers

* URL Rewrite 2.1

* Microsoft SQL Server Data-Tier Application Framework (DacFx) version 2016

Contained Database Authentication

This needs to be enabled to use Web Deploy Packages

The following should be run in SQL Management Studio

1sp_configure 'contained database authentication', 1;
2GO
3RECONFIGURE;
4GO

Solr Setup

The next step is to install and configure Solr, fortunately Jeremy Davis has taken the pain out of this process and produced a script that not only installs Solr it creates and certificate and configures it.

Before running this script, make sure you have 1.8.0_151 64-bit version of JRE installed.

1Param(
2 $solrVersion = "6.6.2",
3 $installFolder = "c:\solr",
4 $solrPort = "8983",
5 $solrHost = "solr",
6 $solrSSL = $true,
7 $nssmVersion = "2.24",
8 $JREVersion = "1.8.0_151"
9)
10
11$JREPath = "C:\Program Files\Java\jre$JREVersion"
12$solrName = "solr-$solrVersion"
13$solrRoot = "$installFolder\$solrName"
14$nssmRoot = "$installFolder\nssm-$nssmVersion"
15$solrPackage = "https://archive.apache.org/dist/lucene/solr/$solrVersion/$solrName.zip"
16$nssmPackage = "https://nssm.cc/release/nssm-$nssmVersion.zip"
17$downloadFolder = "~\Downloads"
18
19## Verify elevated
20## https://superuser.com/questions/749243/detect-if-powershell-is-running-as-administrator
21$elevated = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
22if($elevated -eq $false)
23{
24 throw "In order to install services, please run this script elevated."
25}
26
27function downloadAndUnzipIfRequired
28{
29 Param(
30 [string]$toolName,
31 [string]$toolFolder,
32 [string]$toolZip,
33 [string]$toolSourceFile,
34 [string]$installRoot
35 )
36
37 if(!(Test-Path -Path $toolFolder))
38 {
39 if(!(Test-Path -Path $toolZip))
40 {
41 Write-Host "Downloading $toolName..."
42 Start-BitsTransfer -Source $toolSourceFile -Destination $toolZip
43 }
44
45 Write-Host "Extracting $toolName to $toolFolder..."
46 Expand-Archive $toolZip -DestinationPath $installRoot
47 }
48}
49# download & extract the solr archive to the right folder
50$solrZip = "$downloadFolder\$solrName.zip"
51downloadAndUnzipIfRequired "Solr" $solrRoot $solrZip $solrPackage $installFolder
52
53# download & extract the nssm archive to the right folder
54$nssmZip = "$downloadFolder\nssm-$nssmVersion.zip"
55downloadAndUnzipIfRequired "NSSM" $nssmRoot $nssmZip $nssmPackage $installFolder
56
57# Ensure Java environment variable
58$jreVal = [Environment]::GetEnvironmentVariable("JAVA_HOME", [EnvironmentVariableTarget]::Machine)
59if($jreVal -ne $JREPath)
60{
61 Write-Host "Setting JAVA_HOME environment variable"
62 [Environment]::SetEnvironmentVariable("JAVA_HOME", $JREPath, [EnvironmentVariableTarget]::Machine)
63}
64
65# if we're using HTTP
66if($solrSSL -eq $false)
67{
68 # Update solr cfg to use right host name
69 if(!(Test-Path -Path "$solrRoot\bin\solr.in.cmd.old"))
70 {
71 Write-Host "Rewriting solr config"
72
73 $cfg = Get-Content "$solrRoot\bin\solr.in.cmd"
74 Rename-Item "$solrRoot\bin\solr.in.cmd" "$solrRoot\bin\solr.in.cmd.old"
75 $newCfg = $newCfg | % { $_ -replace "REM set SOLR_HOST=192.168.1.1", "set SOLR_HOST=$solrHost" }
76 $newCfg | Set-Content "$solrRoot\bin\solr.in.cmd"
77 }
78}
79
80# Ensure the solr host name is in your hosts file
81if($solrHost -ne "localhost")
82{
83 $hostFileName = "c:\\windows\system32\drivers\etc\hosts"
84 $hostFile = [System.Io.File]::ReadAllText($hostFileName)
85 if(!($hostFile -like "*$solrHost*"))
86 {
87 Write-Host "Updating host file"
88 "`r`n127.0.0.1`t$solrHost" | Add-Content $hostFileName
89 }
90}
91
92# if we're using HTTPS
93if($solrSSL -eq $true)
94{
95 # Generate SSL cert
96 $existingCert = Get-ChildItem Cert:\LocalMachine\Root | where FriendlyName -eq "$solrName"
97 if(!($existingCert))
98 {
99 Write-Host "Creating & trusting an new SSL Cert for $solrHost"
100
101 # Generate a cert
102 # https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps
103 $cert = New-SelfSignedCertificate -FriendlyName "$solrName" -DnsName "$solrHost" -CertStoreLocation "cert:\LocalMachine" -NotAfter (Get-Date).AddYears(10)
104
105 # Trust the cert
106 # https://stackoverflow.com/questions/8815145/how-to-trust-a-certificate-in-windows-powershell
107 $store = New-Object System.Security.Cryptography.X509Certificates.X509Store "Root","LocalMachine"
108 $store.Open("ReadWrite")
109 $store.Add($cert)
110 $store.Close()
111
112 # remove the untrusted copy of the cert
113 $cert | Remove-Item
114 }
115
116 # export the cert to pfx using solr's default password
117 if(!(Test-Path -Path "$solrRoot\server\etc\solr-ssl.keystore.pfx"))
118 {
119 Write-Host "Exporting cert for Solr to use"
120
121 $cert = Get-ChildItem Cert:\LocalMachine\Root | where FriendlyName -eq "$solrName"
122
123 $certStore = "$solrRoot\server\etc\solr-ssl.keystore.pfx"
124 $certPwd = ConvertTo-SecureString -String "secret" -Force -AsPlainText
125 $cert | Export-PfxCertificate -FilePath $certStore -Password $certpwd | Out-Null
126 }
127
128 # Update solr cfg to use keystore & right host name
129 if(!(Test-Path -Path "$solrRoot\bin\solr.in.cmd.old"))
130 {
131 Write-Host "Rewriting solr config"
132
133 $cfg = Get-Content "$solrRoot\bin\solr.in.cmd"
134 Rename-Item "$solrRoot\bin\solr.in.cmd" "$solrRoot\bin\solr.in.cmd.old"
135 $newCfg = $cfg | % { $_ -replace "REM set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_KEY_STORE=$certStore" }
136 $newCfg = $newCfg | % { $_ -replace "REM set SOLR_SSL_KEY_STORE_PASSWORD=secret", "set SOLR_SSL_KEY_STORE_PASSWORD=secret" }
137 $newCfg = $newCfg | % { $_ -replace "REM set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.jks", "set SOLR_SSL_TRUST_STORE=$certStore" }
138 $newCfg = $newCfg | % { $_ -replace "REM set SOLR_SSL_TRUST_STORE_PASSWORD=secret", "set SOLR_SSL_TRUST_STORE_PASSWORD=secret" }
139 $newCfg = $newCfg | % { $_ -replace "REM set SOLR_HOST=192.168.1.1", "set SOLR_HOST=$solrHost" }
140 $newCfg | Set-Content "$solrRoot\bin\solr.in.cmd"
141 }
142}
143
144# install the service & runs
145$svc = Get-Service "$solrName" -ErrorAction SilentlyContinue
146if(!($svc))
147{
148 Write-Host "Installing Solr service"
149 &"$installFolder\nssm-$nssmVersion\win64\nssm.exe" install "$solrName" "$solrRoot\bin\solr.cmd" "-f" "-p $solrPort"
150 $svc = Get-Service "$solrName" -ErrorAction SilentlyContinue
151}
152if($svc.Status -ne "Running")
153{
154 Write-Host "Starting Solr service"
155 Start-Service "$solrName"
156}
157
158# finally prove it's all working
159$protocol = "http"
160if($solrSSL -eq $true)
161{
162 $protocol = "https"
163}
164Invoke-Expression "start $($protocol)://$($solrHost):$solrPort/solr/#/"

What the SIF?

Sitecore 9 has now introduced the Sitecore Installation Framework (SIF). SIF comprises of a PowerShell module that supports both local and remote installations of Sitecore. It is fully extensible through JSON configuration and PowerShell scripts which deploy Web Deploy Packages into an environment. It is possible to deploy the entire Sitecore Experience Platform or just Experience Management.

To install SIF you can download and install it from the Sitecore Gallery using the following PowerShell commands in an administrator shell:

1Register-PSRepository -Name SitecoreGallery -SourceLocation https://sitecore.myget.org/F/sc-powershell/api/v2
2Install-Module SitecoreInstallFramework

If you get a prompt when installing modules from an untrusted repository, press Y and ENTER

SIF PowerShell

For developer installations, it is also required to install the Sitecore Fundamentals module which allows the creation of self-signed certificates for development environments.

1Install-Module SitecoreFundamentals

If you get a prompt when installing modules from an untrusted repository, press Y and ENTER

Sitecore SIF Fundamentals

Single Server Development Instance

This might have seen like a lot of steps to jump through to get this far however you only need to configure these things once, no matter how many instances of Sitecore you install. Unless you have a very specific scenario, typically you will want an XP Single (XP0) instance for development purposes.

First things first, download the latest version of Sitecore 9 for On-Premises deployment, in my instance, this was Sitecore 9.0.1 rev. 171219 (WDP XP0 packages).zip. Once the file is downloaded make sure that you unblock it.

File properties

Once extracted, go into the extracted files and extract XP0 Configuration files 9.0.1 rev. 171219.zip and copy all the files into the root folder alongside the scwdp zip files.

Also, locate your license.xml file and copy it into this directory.

To simply this process Sitecore has provided a PowerShell script to call SIF with the payload JSON. This will need to be adapted to match the configuration of your local environment.

1# Add the Sitecore MyGet repository to PowerShell
2#Register-PSRepository -Name SitecoreGallery -SourceLocation https://sitecore.myget.org/F/sc-powershell/api/v2
3
4# Install the Sitecore Install Framwork module
5#Install-Module SitecoreInstallFramework
6
7# Install the Sitecore Fundamentals module (provides additional functionality for local installations like creating self-signed certificates)
8#Install-Module SitecoreFundamentals
9
10# Import the modules into your current PowerShell context (if necessary)
11Import-Module SitecoreFundamentals
12Import-Module SitecoreInstallFramework
13
14#define parameters
15$prefix = "sc90"
16$PSScriptRoot = "C:\Users\tomdudfield\Downloads\Sitecore 9.0.1 rev. 171219 (WDP XP0 packages)"
17$XConnectCollectionService = "$prefix.xconnect"
18$sitecoreSiteName = "$prefix.local"
19$SolrUrl = "https://solr:8983/solr"
20$SolrRoot = "C:\solr\solr-6.6.2"
21$SolrService = "solr-6.6.2"
22$SqlServer = "localhost"
23$SqlAdminUser = "sa"
24$SqlAdminPassword = "Pa55word"
25
26#install client certificate for xconnect
27$certParams =
28@{
29 Path = "$PSScriptRoot\xconnect-createcert.json"
30 CertificateName = "$prefix.xconnect_client"
31}
32Install-SitecoreConfiguration @certParams -Verbose
33
34#install solr cores for xdb
35$solrParams =
36@{
37 Path = "$PSScriptRoot\xconnect-solr.json"
38 SolrUrl = $SolrUrl
39 SolrRoot = $SolrRoot
40 SolrService = $SolrService
41 CorePrefix = $prefix
42}
43Install-SitecoreConfiguration @solrParams -Verbose
44
45#deploy xconnect instance
46$xconnectParams =
47@{
48 Path = "$PSScriptRoot\xconnect-xp0.json"
49 Package = "$PSScriptRoot\Sitecore 9.0.1 rev. 171219 (OnPrem)_xp0xconnect.scwdp.zip"
50 LicenseFile = "$PSScriptRoot\license.xml"
51 Sitename = $XConnectCollectionService
52 XConnectCert = $certParams.CertificateName
53 SqlDbPrefix = $prefix
54 SqlServer = $SqlServer
55 SqlAdminUser = $SqlAdminUser
56 SqlAdminPassword = $SqlAdminPassword
57 SolrCorePrefix = $prefix
58 SolrURL = $SolrUrl
59}
60Install-SitecoreConfiguration @xconnectParams -Verbose
61
62#install solr cores for sitecore
63$solrParams =
64@{
65 Path = "$PSScriptRoot\sitecore-solr.json"
66 SolrUrl = $SolrUrl
67 SolrRoot = $SolrRoot
68 SolrService = $SolrService
69 CorePrefix = $prefix
70}
71Install-SitecoreConfiguration @solrParams -Verbose
72
73#install sitecore instance
74$sitecoreParams =
75@{
76 Path = "$PSScriptRoot\sitecore-XP0.json"
77 Package = "$PSScriptRoot\Sitecore 9.0.1 rev. 171219 (OnPrem)_single.scwdp.zip"
78 LicenseFile = "$PSScriptRoot\license.xml"
79 SqlDbPrefix = $prefix
80 SqlServer = $SqlServer
81 SqlAdminUser = $SqlAdminUser
82 SqlAdminPassword = $SqlAdminPassword
83 SolrCorePrefix = $prefix
84 SolrUrl = $SolrUrl
85 XConnectCert = $certParams.CertificateName
86 Sitename = $sitecoreSiteName
87 XConnectCollectionService = "https://$XConnectCollectionService"
88}
89Install-SitecoreConfiguration @sitecoreParams -Verbose

Save this into the directory and run the script.

Install script

Once complete you should have a clean Sitecore 9 instance.

This is the simplest way to get Sitecore installed, for more advanced scenarios the JSON payload or SCWDP's can be adapted to support this. This process can be used for production servers and even to remotely deploy Sitecore, although it is worth turning to the Sitecore official documentation to ensure this process is followed correctly.