How to Set Up Windows Server Update Services (WSUS) on Windows Server 2019
Windows Server Update Services (WSUS) is a free update management solution from Microsoft that allows administrators to centrally manage the distribution of updates released through Microsoft Update to computers in a network. WSUS reduces internet bandwidth consumption by downloading updates once to the WSUS server and distributing them internally. It also gives administrators control over which updates are approved, scheduled, and deployed to specific groups of computers.
Planning WSUS Architecture
For most organizations, a single WSUS server suffices. Larger organizations may use a hierarchy of WSUS servers with an upstream autonomous or replica server at headquarters and downstream servers at branch offices. WSUS 6 on Windows Server 2019 requires at minimum 4 GB of RAM, a fast disk (SSD recommended) for the update content store, and Windows Internal Database (WID) or SQL Server for the metadata database. Plan for 30–40 GB of disk space minimum for update content, though environments with many products and classifications may require 500 GB or more.
Installing WSUS
Install the WSUS role with Windows Internal Database for small to medium deployments. For large environments, use SQL Server:
# Install WSUS with Windows Internal Database
Install-WindowsFeature -Name UpdateServices, UpdateServices-WidDB, UpdateServices-Services, UpdateServices-RSAT -IncludeManagementTools
# Or install WSUS using SQL Server (specify SQL instance)
Install-WindowsFeature -Name UpdateServices, UpdateServices-DB, UpdateServices-Services, UpdateServices-RSAT -IncludeManagementTools
# Verify installation
Get-WindowsFeature -Name UpdateServices*
Running Post-Installation Configuration
After installing the role, run the WSUS post-installation configuration script. This sets up the content directory, configures the database, and performs initial setup:
# Run WSUS post-installation setup
# -ContentDir: where updates will be stored
# -StoreUpdatesLocally: download and store locally (vs. Microsoft Direct)
& 'C:Program FilesUpdate ServicesToolsWsusUtil.exe' postinstall CONTENT_DIR=E:WSUS
# For SQL Server backend:
& 'C:Program FilesUpdate ServicesToolsWsusUtil.exe' postinstall SQL_INSTANCE_NAME="WSUSSERVERWSUS" CONTENT_DIR=E:WSUS
Configuring WSUS Initial Settings with PowerShell
Use the UpdateServices PowerShell module to configure WSUS programmatically. This is more efficient and repeatable than using the GUI:
Import-Module UpdateServices
# Connect to the local WSUS server
$wsus = Get-WsusServer
# Configure WSUS to sync from Microsoft Update
$subscription = $wsus.GetSubscription()
$config = $wsus.GetConfiguration()
# Set upstream server to Microsoft Update
$config.SyncFromMicrosoftUpdate = $true
$config.Save()
# Configure products to synchronize
# First, get all available products
Get-WsusProduct | Select-Object -ExpandProperty Product | Sort-Object Title | Select-Object Title, ID
# Subscribe to specific products
Get-WsusProduct | Where-Object {
$_.Product.Title -in @(
"Windows Server 2019",
"Windows 10",
"Windows 11",
"Microsoft 365 Apps for Enterprise",
"Microsoft SQL Server 2019",
".NET Framework"
)
} | Set-WsusProduct
# Configure update classifications to sync
Get-WsusClassification | Select-Object -ExpandProperty Classification | Sort-Object Title
Get-WsusClassification | Where-Object {
$_.Classification.Title -in @(
"Critical Updates",
"Security Updates",
"Update Rollups",
"Updates",
"Service Packs",
"Definition Updates"
)
} | Set-WsusClassification
Configuring Synchronization Schedule
Configure automatic daily synchronization to keep WSUS current with the latest Microsoft updates. Patch Tuesday is the second Tuesday of each month, so ensure daily sync is configured to pick up updates promptly:
# Configure automatic synchronization
$subscription = $wsus.GetSubscription()
$subscription.SynchronizeAutomatically = $true
$subscription.SynchronizeAutomaticallyTimeOfDay = (New-TimeSpan -Hours 3) # 3:00 AM
$subscription.NumberOfSynchronizationsPerDay = 1
$subscription.Save()
# Trigger an initial manual synchronization
$subscription.StartSynchronization()
# Monitor synchronization progress
$subscription.GetSynchronizationProgress() | Select-Object TotalItems, ProcessedItems, CurrentPhase
# Check synchronization status
$subscription.GetSynchronizationStatus()
$subscription.GetLastSynchronizationInfo()
Configuring Computer Groups
WSUS computer groups allow staged rollouts of updates. A typical structure includes Test/Pilot machines (small group of representative systems updated first), then broader groups for workstations and servers:
# Create computer groups
$wsus.CreateComputerTargetGroup("Pilot-Workstations")
$wsus.CreateComputerTargetGroup("Production-Workstations")
$wsus.CreateComputerTargetGroup("Pilot-Servers")
$wsus.CreateComputerTargetGroup("Production-Servers")
$wsus.CreateComputerTargetGroup("Domain-Controllers")
# List all computer groups
$wsus.GetComputerTargetGroups() | Select-Object Name, Id
# Move a computer to a specific group
$computer = $wsus.GetComputerTargetByName("workstation01.corp.example.com")
$pilotGroup = $wsus.GetComputerTargetGroups() | Where-Object {$_.Name -eq "Pilot-Workstations"}
$computer.AddTargetToGroup($pilotGroup)
# View computers in a group
$pilotGroup.GetComputerTargets() | Select-Object FullDomainName, LastSyncTime, LastReportedStatusTime
Configuring Client-Side Targeting via Group Policy
Point Windows clients at the WSUS server using Group Policy. Configure both the WSUS server URL and the computer target group assignment:
# Configure WSUS server settings in Group Policy
# Computer Configuration > Administrative Templates > Windows Components > Windows Update
# Set the WSUS server URL
Set-GPRegistryValue `
-Name "WSUS Client Settings" `
-Key "HKLMSOFTWAREPoliciesMicrosoftWindowsWindowsUpdate" `
-ValueName "WUServer" `
-Type String `
-Value "http://wsus01.corp.example.com:8530"
Set-GPRegistryValue `
-Name "WSUS Client Settings" `
-Key "HKLMSOFTWAREPoliciesMicrosoftWindowsWindowsUpdate" `
-ValueName "WUStatusServer" `
-Type String `
-Value "http://wsus01.corp.example.com:8530"
# Enable client-side targeting
Set-GPRegistryValue `
-Name "WSUS Client Settings" `
-Key "HKLMSOFTWAREPoliciesMicrosoftWindowsWindowsUpdate" `
-ValueName "TargetGroupEnabled" `
-Type DWord -Value 1
Set-GPRegistryValue `
-Name "WSUS Client Settings" `
-Key "HKLMSOFTWAREPoliciesMicrosoftWindowsWindowsUpdate" `
-ValueName "TargetGroup" `
-Type String `
-Value "Production-Workstations"
# Enable Windows Update to use the WSUS server
Set-GPRegistryValue `
-Name "WSUS Client Settings" `
-Key "HKLMSOFTWAREPoliciesMicrosoftWindowsWindowsUpdateAU" `
-ValueName "UseWUServer" `
-Type DWord -Value 1
# Set automatic update options (4 = auto download and schedule install)
Set-GPRegistryValue `
-Name "WSUS Client Settings" `
-Key "HKLMSOFTWAREPoliciesMicrosoftWindowsWindowsUpdateAU" `
-ValueName "AUOptions" `
-Type DWord -Value 4
Approving Updates
Updates must be approved before WSUS clients will install them. Use a staged approval process starting with the Pilot group:
# Get updates pending approval
$pendingUpdates = Get-WsusUpdate -Approval Unapproved -Status Any
# Approve all critical and security updates for the Pilot group
$pilotGroup = $wsus.GetComputerTargetGroups() | Where-Object {$_.Name -eq "Pilot-Workstations"}
$pendingUpdates | Where-Object {
$_.Update.UpdateClassificationTitle -in @("Critical Updates", "Security Updates")
} | Approve-WsusUpdate -Action Install -TargetGroupName "Pilot-Workstations"
# After testing, approve for all computers
$pendingUpdates | Where-Object {
$_.Update.UpdateClassificationTitle -in @("Critical Updates", "Security Updates")
} | Approve-WsusUpdate -Action Install -TargetGroupName "All Computers"
# View approved updates
Get-WsusUpdate -Approval Approved -Status Any | Select-Object -ExpandProperty Update | `
Select-Object Title, ApprovalStatus, CreationDate | Sort-Object CreationDate -Descending
WSUS Maintenance and Cleanup
WSUS databases grow over time with superseded updates, expired updates, and unused downloads. Run the Server Cleanup Wizard regularly to reclaim disk space and database resources:
# Run WSUS cleanup (remove obsolete, superseded, and declined updates)
$cleanupScope = New-Object Microsoft.UpdateServices.Administration.CleanupScope
$cleanupScope.DeclineExpiredUpdates = $true
$cleanupScope.DeclineSupersededUpdates = $true
$cleanupScope.CleanupObsoleteUpdates = $true
$cleanupScope.CompressUpdates = $true
$cleanupScope.CleanupObsoleteComputers = $true
$cleanupScope.CleanupUnneededContentFiles = $true
$cleanupManager = $wsus.GetCleanupManager()
$result = $cleanupManager.PerformCleanup($cleanupScope)
"Disk space freed: $($result.DiskSpaceFreed / 1GB) GB"
"Updates removed: $($result.UpdatesRemoved)"
"Obsolete computers removed: $($result.ObsoleteComputersDeleted)"
# Reindex the WSUS database (run in SQL Management Studio or via sqlcmd)
# For WID backend:
$SqlScript = @"
USE SUSDB;
EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REBUILD';
EXEC sp_updatestats;
"@
$SqlScript | sqlcmd -S "\.pipeMICROSOFT##WIDtsqlquery" -Q $SqlScript
WSUS is a foundational patch management tool for Windows environments. Combine it with a clear patching policy that defines timelines (e.g., critical patches within 7 days, security patches within 30 days) and use the reporting features to track compliance across all managed computers.