How to Configure Windows Security Baselines with Group Policy on Windows Server 2025

Manually configuring hundreds of Group Policy settings across an enterprise is neither reproducible nor auditable. Microsoft’s Security Compliance Toolkit (SCT) solves this by shipping pre-built security baselines — curated sets of Group Policy Object (GPO) settings that represent Microsoft’s recommended configuration for each Windows Server release. For Windows Server 2025, the toolkit includes baselines for the OS itself, Microsoft Edge, and Microsoft Defender Antivirus. This tutorial walks through downloading and importing the baselines, deploying them to Active Directory, identifying deviations with Policy Analyzer, and creating targeted exception GPOs for settings your organisation legitimately needs to override.

Prerequisites

  • Windows Server 2025 domain controller running Active Directory Domain Services
  • An account with Domain Admin or Group Policy Creator Owners membership
  • Group Policy Management Console (GPMC) — installed via Install-WindowsFeature GPMC
  • Internet access to download the Security Compliance Toolkit (or an internal mirror)
  • A test Organisational Unit (OU) containing non-production servers for initial validation

Step 1: Download the Security Compliance Toolkit

The Security Compliance Toolkit is a free download from the Microsoft Download Center. It ships as a self-extracting ZIP that contains the baselines, LGPO.exe, PolicyAnalyzer.exe, and supporting scripts.

# Download SCT to a staging folder (PowerShell 7 recommended)
$sctUrl   = 'https://download.microsoft.com/download/SCT/Windows-Server-2025-Security-Baseline.zip'
$stagingDir = 'C:SCTWindowsServer2025'

New-Item -ItemType Directory -Path $stagingDir -Force | Out-Null

Invoke-WebRequest -Uri $sctUrl -OutFile "$stagingDirWS2025-Baseline.zip" -UseBasicParsing

Expand-Archive -Path "$stagingDirWS2025-Baseline.zip" `
               -DestinationPath $stagingDir -Force

Get-ChildItem $stagingDir -Recurse | Select-Object FullName

After extraction you will find a folder structure similar to:

C:SCTWindowsServer2025
  ├── Documentation
  ├── GP Reports
  ├── GPOs
  │   ├── MSFT Windows Server 2025 - Domain Controller
  │   ├── MSFT Windows Server 2025 - Member Server
  │   └── MSFT Windows Server 2025 - Credential Guard
  ├── Scripts
  │   ├── Baseline-LocalInstall.ps1
  │   └── MapGuidsToGpoNames.ps1
  └── Tools
      ├── LGPO.exe
      └── PolicyAnalyzer

Step 2: Apply a Baseline to a Local Machine with LGPO.exe

LGPO.exe (Local Group Policy Object tool) imports baseline settings into the local machine policy, making it ideal for standalone servers or for validating the baseline before domain deployment. The /g flag imports from a GPO backup folder:

# Apply the Member Server baseline locally
$lgpoExe    = 'C:SCTWindowsServer2025ToolsLGPO.exe'
$gpoBackup  = 'C:SCTWindowsServer2025GPOsMSFT Windows Server 2025 - Member Server'

# /g imports from a GPO backup folder (the folder containing {GUID} subfolders)
& $lgpoExe /g $gpoBackup

# To import from a raw LGPO text file use /t instead:
# & $lgpoExe /t 'C:SCT...registry.pol.txt'

# Verify local policy was updated
gpresult /r /scope computer

To export the current local policy as a backup before making changes, use the /b flag:

# Backup current local GPO before importing baseline
$backupPath = "C:SCTBackupsPreBaseline_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
New-Item -ItemType Directory -Path $backupPath -Force | Out-Null

& $lgpoExe /b $backupPath
Write-Host "Local GPO backed up to $backupPath"

Step 3: Import the Baseline into Active Directory with GPMC

For domain deployments, import the baseline as a new GPO in Active Directory using GPMC. PowerShell automates the process and avoids the manual import wizard:

Import-Module GroupPolicy

$domainName   = (Get-ADDomain).DNSRoot
$gpoName      = 'MSFT WS2025 Member Server Baseline'
$backupFolder = 'C:SCTWindowsServer2025GPOs'
$backupId     = '{GUID-OF-MEMBER-SERVER-BACKUP}'   # Replace with actual GUID from the GPOs folder

# Create a new blank GPO
$newGpo = New-GPO -Name $gpoName -Domain $domainName -Comment 'Microsoft Security Baseline — WS2025 Member Server'

# Import the baseline settings into the new GPO
Import-GPO -BackupId $backupId `
           -TargetName $gpoName `
           -Path $backupFolder `
           -Domain $domainName

Write-Host "GPO '$gpoName' created with ID: $($newGpo.Id)"

To discover the GUID of the backup folder automatically:

# Find backup GUIDs from bkupInfo.xml files in the GPO backup directory
Get-ChildItem -Path 'C:SCTWindowsServer2025GPOs' -Recurse -Filter 'bkupInfo.xml' |
    ForEach-Object {
        $xml = [xml](Get-Content $_.FullName)
        [PSCustomObject]@{
            GPOName  = $xml.BackupInst.GPODisplayName.'#text'
            BackupId = $xml.BackupInst.ID.'#text'
            Path     = $_.DirectoryName
        }
    }

Step 4: Link the GPO to a Test OU First

Never link a new baseline directly to the domain root or a tier-0 OU on first deployment. Link it to a dedicated test OU, apply gpupdate /force on a test server, and validate functionality before broader rollout:

$testOuDN = 'OU=WS2025-Test,OU=Servers,DC=contoso,DC=com'
$gpoName  = 'MSFT WS2025 Member Server Baseline'

# Link GPO to test OU (order 1 = highest precedence within the OU)
New-GPLink -Name $gpoName -Target $testOuDN -LinkEnabled Yes -Order 1

# Force policy refresh on a specific test server
Invoke-Command -ComputerName 'TESTSVR01' -ScriptBlock { gpupdate /force /wait:0 }

# Retrieve RSoP (Resultant Set of Policy) summary remotely
Get-GPResultantSetOfPolicy -Computer 'TESTSVR01' -ReportType Html `
    -Path 'C:SCTReportsTESTSVR01-RSoP.html'

Step 5: Use Policy Analyzer to Identify Deviations

Policy Analyzer is a GUI tool included in the SCT that compares two policy sets — typically your live GPO backup against the Microsoft baseline — and highlights every setting that differs. Run it from the command line to produce a CSV delta report:

# Export current domain GPO as a backup for comparison
$liveBackupPath = "C:SCTBackupsLive_$(Get-Date -Format 'yyyyMMdd')"
New-Item -ItemType Directory -Path $liveBackupPath -Force | Out-Null

Backup-GPO -Name 'MSFT WS2025 Member Server Baseline' `
           -Path $liveBackupPath `
           -Comment 'Live baseline snapshot for Policy Analyzer comparison'

# PolicyAnalyzer.exe is a GUI tool — launch it pointing at both policy sets:
# 1. File > Add > Browse to baseline GPO backup folder
# 2. File > Add > Browse to live backup folder
# 3. View > Compare to see all differences highlighted

# From command line, export the policy set to XML for scripted diffing:
$policyAnalyzerExe = 'C:SCTWindowsServer2025ToolsPolicyAnalyzerPolicyAnalyzer.exe'
Start-Process $policyAnalyzerExe

Step 6: Create an Exceptions GPO to Override Specific Settings

Some baseline settings will conflict with legitimate business requirements. The correct pattern is to create a separate higher-precedence GPO that overrides only the specific conflicting settings, leaving the baseline GPO untouched and upgradeable:

# Create the exceptions GPO
$exceptionsGpoName = 'WS2025 Baseline Exceptions — AppTeam'
New-GPO -Name $exceptionsGpoName -Domain $domainName `
        -Comment 'Targeted overrides to Microsoft WS2025 baseline'

# Example: re-enable a specific logon right that the baseline removed
# Use Set-GPRegistryValue for registry-based policy settings
Set-GPRegistryValue -Name $exceptionsGpoName `
    -Key 'HKLMSOFTWAREMicrosoftWindows NTCurrentVersionWinlogon' `
    -ValueName 'CachedLogonsCount' `
    -Type DWord `
    -Value 2

# Link the exceptions GPO to the same OU with a lower order number (higher precedence)
# so it wins over the baseline GPO when both are linked
New-GPLink -Name $exceptionsGpoName -Target $testOuDN -LinkEnabled Yes -Order 1

# Move baseline GPO to order 2
Set-GPLink -Name $gpoName -Target $testOuDN -Order 2

Write-Host "Exceptions GPO linked at higher precedence than baseline"

Step 7: Promote to Production and Document

Once testing is complete, link the baseline and exceptions GPOs to your production server OUs. Use Get-GPInheritance to audit the final link order and document the rationale for every exception in the GPO comment field:

$prodOuDN = 'OU=MemberServers,OU=Servers,DC=contoso,DC=com'

New-GPLink -Name $exceptionsGpoName -Target $prodOuDN -LinkEnabled Yes -Order 1
New-GPLink -Name $gpoName           -Target $prodOuDN -LinkEnabled Yes -Order 2

# Audit final inheritance chain
Get-GPInheritance -Target $prodOuDN | Select-Object -ExpandProperty GpoLinks |
    Sort-Object Order |
    Format-Table Order, DisplayName, Enabled, Enforced -AutoSize

Security baselines are living documents. Microsoft releases updated SCT packages with every major Windows Server servicing update, and the delta between versions is typically small but security-critical. Establish a quarterly review cycle: download the latest SCT, run Policy Analyzer against your current production baseline GPO, evaluate each changed setting against your risk register, and update the baseline GPO in a test OU before promoting. This disciplined process keeps your environment aligned with Microsoft’s threat-informed recommendations without disrupting business operations.