SharePoint Infrastructure Workshop Topics

I’ve run Infrastructure Workshops for many SharePoint implementation projects over the years. The objective of the workshop is to figure our how the farm(s) will be implemented in the customer’s environment. A few important decisions are made based on the outcome of the workshop:

  • Server and storage sizing
  • Network placement
  • Service account management
  • DR strategy
  • Farm configuration
  • etc.

I am sharing the checklist here in case it helps. 🙂 Feel free to leave your questions or feedback in the comment.

Infra Workshop Topics


SharePoint Three-Tier Network Zoning Architecture

This topic came when there were policies in some organizations that require SharePoint to comply with the “three-tier architecture” requirement, meaning WFE, APP and DB should be in three network zones, and WFEs CANNOT connect to the DBs directly! It is common to see SharePoint farms servers placed in three zones, but most of the time WFEs are allowed to connect to the DB Server. However, this is not acceptable to the organizations that has the “three-tier” policy in place.

I saw in some projects a proxy server is implemented in the APP zone to bridge WFE and DB. It works. However, that proxy can easily become a bottleneck in larger implementations. So far the most common way of implementation is to place one or multiple reverse proxies in the Web zone as the web layer, shifting the SharePoint WFEs to the App zone together with the App servers.

{update April 2018} What I propose in this post is an alternative using technologies on SharePoint. However, based on practical experiences, this approach is more theoretical than practical. So far, there is no production implementation yet. {/update April 2018}

This alternative approach leverages the Request Management of SharePoint. With that you may say SharePoint actually supports the 3-tier requirement. How Request Manager works is elaborated on TechNet. The design here is to:

  • Put the WFEs in the APP Zone so they can connect to the databases directly.
  • Put a dedicated request management farm in the Web Zone in between the Load Balancer and the WFEs, with databases in the same zone.

Good 3-thier Architecture

This way, the Request Management layer serves as the web layer interacting with user requests. The WFEs in the APP Zone become the content serving components that retrieve data from the databases at the back end, while they are in the secure internal APP network zone.

Q: is it OK to place a database server of the Request Management farm in the web zone?

A: Yes, there is no user data stored in the database, only farm service configuration data. And the firewall rules should be restricting network traffic to the DB server to come only from the Request Management Farm servers.

Q: When the actual WFEs in the APP zone servers content back to the users, do they transfer it directly to the users?

A: No, it responds back to the users through the Request Management farm. This is actually the key part that makes the architecture above possible as users are not able to reach the App Zone.

Q: Should Office Web Apps Server be placed in the Web Zone or the same zone as the actual WFEs?

A: It must be reachable by the end users directly, so it should be more suitable to be in the Web Zone.

PS: The diagram below shows a bad design example that uses a proxy:

Bad 3-tier Architecture

Real Zero-Downtime Patching in SharePoint 2016

It is exciting to have Zero-Downtime Patching (ZDP) capability in SharePoint 2016. However, it requires more effort than most of us might have initially thought. While it is straightforward for other components, it requires a bit more care on Distributed Cache.

Distributed Cache doesn’t support High Availability the way that other services do. While multiple Distributed Cache servers in your SharePoint farm can help distribute the load, the data cached on each Distributed Cache server is NOT replicated to the other Distributed Cache servers. If a Distributed Cache server unexpectedly goes down, the data cached on that server will be lost. That means if you install patches and upgrades a Distributed Cache server without gracefully shutting it down, you will cause data lost!

One may argue that if there are three Distributed Cache hosts on the farm, there will be high availability for the Distributed Cache as AppFabric has as cluster quorum model. That is not true as SharePoint is not using that model!

Therefore, if you have workloads that heavily depends on Distributed Cache and have high availability requirements, add Gracefull Shutdown of the Distributed Cache Service into the patching process to have true Zero-Downtime.

Gracefully shutdown DCS:

Monitor SharePoint 2013 Search Components with PowerShell

This is a prototype for a PowerShell script that monitors the status of each component of Search Service Application in SharePoint 2013. This script can be saved  to a .ps1 file and run by the Window Task scheduler periodically. If it detects that any of the component is not in the “Active” state, it automatically sends an email to the administrator.

Add-PSSnapin Microsoft.SharePoint.PowerShell
#Declare variables for later use.
$ssa = Get-SPEnterpriseSearchServiceApplication
$status = Get-SPEnterpriseSearchStatus -SearchApplication $ssa
#Create an empty array to store any component that is not active.
$unhealthy = @()
#Loop through each component status, and store any one that is not active to the array.
$number = 0
$status | foreach {
if ($_.state -ne "active"){
$unhealthy +=$number.ToString() + ". " + $ + "`n"

#If there is any component that is not active, send an email to the admin with the component name in the email body.
if ($unhealthy.count -gt 0) {
$result = "The components below are not active:`n " + $unhealthy
$params = @{'To'=''
'Subject'='Attention! Search Service Components Unhealthy'
Send-MailMessage @params

The script has been tested with a single server farm with a single Search Service Application. If your scenario is different, you should adjust the script accordingly.

Batch Enabling Auditing across Many SharePoint Sites

If you are only looking for the script and are not interested what else I say, just grab them here:

#Define the function Enable-Auditing. The URL parameter accepts pipeline input. It also enables log trimming, and log retention time is set to 30 days. This part is kind of "hardcoded", but it should not be too difficult to change it. 
function Enable-Auditing {
$site = Get-SPSite $Url;
$site.TrimAuditLog = $true;
$site.AuditLogTrimmingRetention = 30;
$site.Audit.AuditFlags = $AuditedActions;
Run the commands to apply the settings to specific Site Collections. For the -AuditedAction parameter, input any of the following:
"All" to audit all auditable actions.
"None" to disable auditing
An array of action names to enable auditing a specific set of actions to audit, e.g. "Update", "Delete", "Search". 
Check MSDN documentation for a complete list of auditable actions:
Enable-Auditing -URL -AuditedActions "Update", "Delete"

As the -URL parameter accepts pipeline inputs, batch action can be done to multiple site collection with one line of command such as the one below:

#The command below enables auditing Update and Delete actions on all Site Collections whose URL contains "hr".
Get-SPSite -WebApplication -Limit All | ? {$_.url -like "*hr*"} | ForEach-Object {Enable-Auditing -Url $_.url -AuditedActions "Update", "Delete"}

OK, if you are interested in my monologue discussing this function, please read on. Otherwise, the content above is all you need.

How do you make sure auditing is enabled all the time? How may Site Collections do you need to manage? Does each Site Collection has its own Site Collection Administrator?

Site Collection Administrators has the permission to change site audit settings. That’s a potential risk since they can intentionally or unintentionally change the audit settings, while auditing is usually an organization-wide policy that needs to be enforced. Sometimes, turning on unnecessary auditing is bad as well as it will make the content DB grow faster. A single piece of audit log is about 1KB. Imagine, 1000 people are visiting 100 locations in a day!

One solution is to create a PowerShell scripts running under a task scheduler that enforces auditing policies, including:

  • Actions to audit
  • Whether to enable audit log trimming
  • If log trimming enabled, how many days of log to retain

In SharePoint Management Shell, there is no direct cmdlet for this purpose yet. We can define a function to make batch operations easier.

If you run Get-Member on a SPSite object, you will find that there are a few properties related to auditing:

  • Audit
  • AuditLogTrimmingCallout
  • AuditLogTrimmingRetention

To enable/disable auditing, the trick is to set the value of the SPSite.Audit.AuditFlags property. Based on tests, it accepts strings or array of strings. So there comes the code at the beginning of this post.

Move SharePoint 2013 Search Index Location

Task: Move search index from D: drive to E: drive on the existing Index Servers.
Search topology:



#Discover current search topology information with documentation.

$ssa = Get-SPEnterpriseSearchServiceApplication
$old = Get-SPEnterpriseSearchTopology -SearchApplication $ssa -Active
Get-SPEnterpriseSearchServiceApplication >C:\SSA_Info.txt
Get-SPEnterpriseSearchComponent -SearchTopology $old >c:\oldtopology.txt
Get-SPEnterpriseSearchStatus -SearchApplication $ssa

#Define parameters for the move.

<# $hostA = Get-SPEnterpriseSearchServiceInstance -Identity "Server1" $hostB = Get-SPEnterpriseSearchServiceInstance -Identity "Server2" #>
$hostC = Get-SPEnterpriseSearchServiceInstance -Identity "Server3"
$hostD = Get-SPEnterpriseSearchServiceInstance -Identity "Server4"
$hostE = Get-SPEnterpriseSearchServiceInstance -Identity "Server5"
$hostF = Get-SPEnterpriseSearchServiceInstance -Identity "Server6"
$indexPath = "E:\Search_Index01"

#Clone the current active topology

$clone = New-SPEnterpriseSearchTopology -SearchApplication $ssa -Clone -SearchTopology $old

#To the cloned topology, add new Index components using new path.

New-SPEnterpriseSearchIndexComponent -SearchTopology $clone -SearchServiceInstance $hostC -IndexPartition 0 -RootDirectory $indexPath
New-SPEnterpriseSearchIndexComponent -SearchTopology $clone -SearchServiceInstance $hostD -IndexPartition 0 -RootDirectory $indexPath
New-SPEnterpriseSearchIndexComponent -SearchTopology $clone -SearchServiceInstance $hostE -IndexPartition 1 -RootDirectory $indexPath
New-SPEnterpriseSearchIndexComponent -SearchTopology $clone -SearchServiceInstance $hostF -IndexPartition 1 -RootDirectory $indexPath

#Set the new (cloned) topology as active. This step takes the most time.

Set-SPEnterpriseSearchTopology -Identity $clone

#Discover the component info in the new topology.

Get-SPEnterpriseSearchComponent -SearchTopology $clone >c:\InterimTopology.txt

#Confirm that all the components are ready. Also check in the Central Admin Site for the status.

Get-SPEnterpriseSearchStatus -SearchApplication $ssa

Remove the older index components. ONLY DO THIS AFTER NEWLY ADDED INDEX COMPONENTS ARE ACTIVE. You need to clone the latest topology and modify the new cloned topology. Then set the new clone as active when modification is done. Double Check in the InterimTopology.txt the info on the components to identify the components to remove.

IndexPartitionOrdinal : 0
RootDirectory : E:\Search_Index01
ComponentId :
TopologyId :
ServerId :
Name : IndexComponent4
ServerName : SearchServer04

$active = Get-SPEnterpriseSearchTopology -SearchApplication $ssa -Active
$newclone = New-SPEnterpriseSearchTopology -SearchApplication $ssa -Clone -SearchTopology $active

$comp1=Get-SPEnterpriseSearchComponent -SearchTopology $newclone | ? {$_.Name -eq "IndexComponent1"}
$comp2=Get-SPEnterpriseSearchComponent -SearchTopology $newclone | ? {$_.Name -eq "IndexComponent2"}
$comp3=Get-SPEnterpriseSearchComponent -SearchTopology $newclone | ? {$_.Name -eq "IndexComponent3"}
$comp4=Get-SPEnterpriseSearchComponent -SearchTopology $newclone | ? {$_.Name -eq "IndexComponent4"}

Remove-SPEnterpriseSearchComponent -Identity $comp1 -SearchTopology $newclone
Remove-SPEnterpriseSearchComponent -Identity $comp2 -SearchTopology $newclone
Remove-SPEnterpriseSearchComponent -Identity $comp3 -SearchTopology $newclone
Remove-SPEnterpriseSearchComponent -Identity $comp4 -SearchTopology $newclone

Set-SPEnterpriseSearchTopology -Identity $newclone

# Optionally, you can use a for loop to run through a list of components to remove. But I prefer the lines above as it shows explicitly the actual action to take.

#Confirm that all the components are ready. Also check in the Central Admin Site for the status.

Get-SPEnterpriseSearchStatus -SearchApplication $ssa

#Discover the component info in the final topology.

Get-SPEnterpriseSearchComponent -SearchTopology $newclone >c:\FinalTopology.txt

#Remove the old topologies

Get-SPEnterpriseSearchTopology -SearchApplication $ssa
Remove-SPEnterpriseSearchTopology -Identity < > 

Getting Rid of GUIDs in DB names in an Exiting SharePoint Farm

DBAs hate the GUID appended to a database name. Everyone does! But that will happen if the farm and the Service Applications within are created with a wizard.



To make sure the database names are “clean”, farm admins can create the farm using psconfig.exe and create the Service Applications and Content Catabases with PowerShell. But what if a farm has been created and the databases already have GUID in their names? When you just take over a new farm, this may be the case, and you may be lucky enough to be assigned the task to change the names. 🙂

Just do the steps below to get rid of the GUIDs:

For the Central Administration site content database, you need to move the site to a new Content Database. Follow the steps:

  1. Create a new databases with proper names and configuration.
  2. Move the sites with Move-SPSite PowerShell cmdlet to move the sites to the new databases.
  3. Verify the sites are working correctly after the move.
  4. Delete the old databases.

For the user Content Databases, you can rename the databases. Follow the steps:

  1. Dismount the database from SharePoint Web Applications with Dismount-SPContentDatabase PowerShell cmdlet.
  2. Rename the dismounted database in SQL Server with ALTER DATABASE T-SQL command or in the Object Explorer.
  3. Mount the renamed database to SharePoint Web Applications with Mount-SPContentDatabase PowerShell cmdlet.

For Service Application databases, you need to rename the databases with additional actions and it is specific to each service application. Check this TechNet article to find information for the service applications you are using.