Automating the SharePoint 2013 installation and creating a farm with PowerShell

SharePoint 2013

SharePoint 2013 was released to manufacturing and this week the media became available for MSDN and TechNet subscribers.

We've had an opportunity here at Habanero to start setting up some SP2013 VMs that our delgates will have available to them during the SharePoint Conference.

I finished building a SharePoint farm yesterday to test out my SharePoint 2010 automation scripts to see if they've held up and so far it looks good. The documentation's not yet up on TechNet, but the work I did explaining config.xml last year in Automating the SharePoint 2010 installation looks to be the same. I used the same config.xml (with a SharePoint 2013 product key) and ran an unattended installation. When the documentation becomes available I hope there to be few changes.

I have a script that I use to initially create the configuration database and Central Administration site that I blogged about earlier this year in Create a SharePoint 2010 farm with PowerShell, I like to call it the SharePoint Configuration Powershell Wizard in that it creates a new farm and does all the associated tasks performed by the configuration wizard. I tested it out yesterday against SP2013 RTM and it worked without any issue.

I've made some improvements since then so let's go through them and see how this script works.

First I use my credential hash table to define the credentials for accounts I'll use in the farm. There's the farm account, a service account for the service application pools, another for the web application.

# Service accounts
$DOMAIN = "CONTOSO"
$accounts = @{}
$accounts.Add("SPFarm", @{"username" = "sp2013-farm"; "password" = "Password123"})
$accounts.Add("SPWebApp", @{"username" = "sp2013-ap-webapp"; "password" = "Password123"})
$accounts.Add("SPSvcApp", @{"username" = "sp2013-ap-service"; "password" = "Password123"})


Foreach ($account in $accounts.keys) {
	$accounts.$account.Add(`
	"credential", `
	(New-Object System.Management.Automation.PSCredential ($DOMAIN + "\" + $accounts.$account.username), `
	(ConvertTo-SecureString -String $accounts.$account.password -AsPlainText -Force)))
}

Next I set up a SQL Server client alias. I include this here because I like to reuse my scripts and I don't ever want to forget to use an alias. The script I use is based on Zach's post Create a SQL Alias with a PowerShell Script. Note that in this example, I have a SQL Server isntance on the same server. With some changes you can point the alias to another server or an instance on a non-standard port.

#This is the name of your SQL Alias
$AliasName = "SPFarmAlias"
 
#This is the name of your SQL server (the actual name!)
# In this case we're using the current computer name as we are assuming SharePoint and SQL are on the same server
# Change this if this isn't the case in your environment!
$ServerName = $env:computername
 
#These are the two Registry locations for the SQL Alias locations
$x86 = "HKLM:\Software\Microsoft\MSSQLServer\Client\ConnectTo"
$x64 = "HKLM:\Software\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo"
 
#We're going to see if the ConnectTo key already exists, and create it if it doesn't.
if ((test-path -path $x86) -ne $True)
{
    write-host "$x86 doesn't exist"
    New-Item $x86
}
if ((test-path -path $x64) -ne $True)
{
    write-host "$x64 doesn't exist"
    New-Item $x64
}
 
#Adding the extra "fluff" to tell the machine what type of alias it is
$TCPAlias = ("DBMSSOCN," + $ServerName)
 
#Creating our TCP/IP Aliases
New-ItemProperty -Path $x86 -Name $AliasName -PropertyType String -Value $TCPAlias
New-ItemProperty -Path $x64 -Name $AliasName -PropertyType String -Value $TCPAlias

Now that the alias is in place we can start with the farm configuration.

Let's define our values for the farm passphrase, SQL Server name, configuration and Central Administration database names, and the CA port and authentication:

# Farm configuration

$configPassphrase = "SharePoint 2013 is the latest version of SharePoint!"
$s_configPassphrase = (ConvertTo-SecureString -String $configPassphrase -AsPlainText -force)

$serverDB = $AliasName
$dbConfig = "SP2013_Configuration"
$dbCentralAdmin = "SP2013_Content_CentralAdministration"

$caPort = 11111
$caAuthProvider = "NTLM"

We've prepared everything we need, let's create the farm:

Add-PSSnapin Microsoft.SharePoint.PowerShell

Write-Output "Creating the configuration database $dbConfig"
New-SPConfigurationDatabase `
-DatabaseName $dbConfig `
-DatabaseServer $serverDB `
-AdministrationContentDatabaseName $dbCentralAdmin `
-Passphrase  $s_configPassphrase `
-FarmCredentials $accounts.SPFarm.credential

# Check to make sure the farm exists and is running. if not, end the script
$farm = Get-SPFarm
if (!$farm -or $farm.Status -ne "Online") {
	Write-Output "Farm was not created or is not running"
	exit
}

Write-Output "Create the Central Administration site on port $caPort"
New-SPCentralAdministration `
-Port $caPort `
-WindowsAuthProvider $caAuthProvider

There is some error handling to check if the farm has been created after running the New-SPConfigurationDatabase cmdlet. If there was some sort of error the script will end at this point as there is no point in continuing and letting your screen fill up with red exception text. While testing this with SP2013 I received errors like:

  1. SQL Server was the wrong version (SQL Server 2008 R2 RTM). It told me the version was not enough and to upgrade (I upgraded to SP2)
  2. The configuration database already existed (from a previous configuration attempt) and that it could not be used because it already had a schema
  3. SQL Server had the wrong "max degree of paralelism value. It said it should be a value of 1 and I set this by running the following query in SQL Server:
    sp_configure 'show advanced options', 1;
    GO
    RECONFIGURE WITH OVERRIDE;
    GO
    sp_configure 'max degree of parallelism', 1;
    GO
    RECONFIGURE WITH OVERRIDE;
    GO

This SQL query and more information about the max degree of parallelism option are on the MSDN: max degree of parallelism Option

With SP2010 I often experienced an exception because the New-SPConfigurationDatabase failed to run. This was usually when I was repeatively re-running my script during testing. I didn't encounter the issue yesterday but if it had happend the script would have stopped.

In most cases when it does stop there is a configuration database that has been partially created in SQL Server. If you want to run this script again you'll have to delete the existing database or rename the database in your script. Of course, if the script can't connect to SQL Server there won't be a database to delete, though the script will stop at this point so you can troubleshoot the connectivity.

Now that we've created the configuration database and Central Administration, we need to do the other 5 or 6 tasks that Central Administration does, namely:

  • Install Help Collections
  • Initialize security
  • Install services
  • Register features
  • Install Application Content

How do I know the configuration wizard does these things? Microsoft documented it for SharePoint 2007. They used to have a page that detailed setting the farm up with PSCONFIG.EXE and listed all these steps. That article is long gone (or at least I can't find it), but they still reference part of it in Command-line reference for the SharePoint Products and Technologies Configuration Wizard (Office SharePoint Server):

psconfig.exe –cmd configdb 
–cmd helpcollections 
–cmd secureresources 
–cmd services 
–cmd installfeatures 
–cmd adminvs 
–cmd evalprovision 
–cmd applicationcontent 

You can ignore evalprovision, that's for standalone installations only. If you needed any further reason to never use standalone mode, note what that command does: "Provisions this server as a stand-alone (evaluation mode) server." Standalone mode is for evaluation, it's not meant to be for any real production use.

The other command you can ignore is the adminvs command which sets up Central Administration. Those other commands (helpcollections, secureresources, services, installfeatures, applicationcontent) are the same ones I've identified as tasks we need to run next:

# Perform the config wizard tasks

Write-Output "Install Help Collections"
Install-SPHelpCollection -All 

Write-Output "Initialize security"
Initialize-SPResourceSecurity 

Write-Output "Install services"
Install-SPService 

Write-Output "Register features"
Install-SPFeature -AllExistingFeatures 

Write-Output "Install Application Content"
Install-SPApplicationContent

Now we have a farm! It doesn't do much, pretty much all we can do is continue configuring it. But to do that we need to register our service accounts as managed accounts:

# Add managed accounts
Write-Output "Creating managed accounts ..."
New-SPManagedAccount -credential $accounts.SPWebApp.credential
New-SPManagedAccount -credential $accounts.SPSvcApp.credential
New-SPManagedAccount -credential $accounts.SPCrawl.credential

And with that, we can open up Central Administration and start creating web applications and services or we can continue setting everything up with PowerShell.

Oh, and before I forget, I did a quick check to see what the RTM build numbers are:

PS> (get-spfarm).buildversion

Major  Minor  Build  Revision
-----  -----  -----  --------
15     0      4420   1017

And Central Administration reports the same, RTM is build 15.0.4420.1017

Welcome SharePoint 2013!

For reference, here's the full script:

############################################################
# Configure-SPFarm.ps1
# Configures a SharePoint 2013 farm with:
#   Configuration Database
#   Central Administation web application and site
#
# Jason Warren, Habanero Consulting Group
# jwarren@habaneroconsulting.com
# Last modified Oct 25, 2012
#
############################################################

# Service accounts
$DOMAIN = "CONTOSO"
$accounts = @{}
$accounts.Add("SPFarm", @{"username" = "sp2013-farm"; "password" = "Password123"})
$accounts.Add("SPWebApp", @{"username" = "sp2013-ap-webapp"; "password" = "Password123"})
$accounts.Add("SPSvcApp", @{"username" = "sp2013-ap-service"; "password" = "Password123"})


Foreach ($account in $accounts.keys) {
	$accounts.$account.Add(`
	"credential", `
	(New-Object System.Management.Automation.PSCredential ($DOMAIN + "\" + $accounts.$account.username), `
	(ConvertTo-SecureString -String $accounts.$account.password -AsPlainText -Force)))
}


# SQL Server client alias
# From Zach's post: /Insights/Create-a-SQL-Alias-with-a-PowerShell-Script.aspx


#This is the name of your SQL Alias
$AliasName = "SPFarmAlias"
 
#This is the name of your SQL server (the actual name!)
# In this case we're using the current computer name as we are assuming SharePoint and SQL are on the same server
# Change this if this isn't the case in your environment!
$ServerName = $env:computername
 
#These are the two Registry locations for the SQL Alias locations
$x86 = "HKLM:\Software\Microsoft\MSSQLServer\Client\ConnectTo"
$x64 = "HKLM:\Software\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo"
 
#We're going to see if the ConnectTo key already exists, and create it if it doesn't.
if ((test-path -path $x86) -ne $True)
{
    write-host "$x86 doesn't exist"
    New-Item $x86
}
if ((test-path -path $x64) -ne $True)
{
    write-host "$x64 doesn't exist"
    New-Item $x64
}
 
#Adding the extra "fluff" to tell the machine what type of alias it is
$TCPAlias = ("DBMSSOCN," + $ServerName)
 
#Creating our TCP/IP Aliases
New-ItemProperty -Path $x86 -Name $AliasName -PropertyType String -Value $TCPAlias
New-ItemProperty -Path $x64 -Name $AliasName -PropertyType String -Value $TCPAlias

# Open cliconfig to verify the aliases
Start-Process C:\Windows\System32\cliconfg.exe
Start-Process C:\Windows\SysWOW64\cliconfg.exe



# Farm configuration

$configPassphrase = "SharePoint 2013 is the latest version of SharePoint!"
$s_configPassphrase = (ConvertTo-SecureString -String $configPassphrase -AsPlainText -force)

$serverDB = $AliasName
$dbConfig = "SP2013_Configuration"
$dbCentralAdmin = "SP2013_Content_CentralAdministration"

$caPort = 11111
$caAuthProvider = "NTLM"

########################################
# Create the farm

Add-PSSnapin Microsoft.SharePoint.PowerShell

Write-Output "Creating the configuration database $dbConfig"
New-SPConfigurationDatabase `
-DatabaseName $dbConfig `
-DatabaseServer $serverDB `
-AdministrationContentDatabaseName $dbCentralAdmin `
-Passphrase  $s_configPassphrase `
-FarmCredentials $accounts.SPFarm.credential

# Check to make sure the farm exists and is running. if not, end the script
$farm = Get-SPFarm
if (!$farm -or $farm.Status -ne "Online") {
	Write-Output "Farm was not created or is not running"
	exit
}

Write-Output "Create the Central Administration site on port $caPort"
New-SPCentralAdministration `
-Port $caPort `
-WindowsAuthProvider $caAuthProvider


# Perform the config wizard tasks

Write-Output "Install Help Collections"
Install-SPHelpCollection -All 

Write-Output "Initialize security"
Initialize-SPResourceSecurity 

Write-Output "Install services"
Install-SPService 

Write-Output "Register features"
Install-SPFeature -AllExistingFeatures 

Write-Output "Install Application Content"
Install-SPApplicationContent


# Add managed accounts
Write-Output "Creating managed accounts ..."
New-SPManagedAccount -credential $accounts.SPWebApp.credential
New-SPManagedAccount -credential $accounts.SPSvcApp.credential
New-SPManagedAccount -credential $accounts.SPCrawl.credential

#Start Central Administration
Write-Output "Starting Central Administration"
& 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\BIN\psconfigui.exe' -cmd showcentraladmin

Write-Output "Farm build complete."

References

Stories say it best.

Are you ready to make your workplace awesome? We're keen to hear what you have in mind.

Interested in learning more about the work we do?

Explore our culture and transformation services.

Our commitment to reconciliation

Learn how Habanero is responding to the Truth and Reconciliation Calls to Action as a settler-owned company operating on Indigenous territories across what is now called Canada.

Read about our commitment