# Enterprise Endpoint Management with SCCM/MECM: A Complete Homelab Build # https://www.zadran.net/guides/enterprise-endpoint-management-sccm-homelab # Generated from the guide, last updated 2026-10-18. # # NO WARRANTY. This script is provided as is. You are responsible for # understanding what it does before running it, and for the consequences. # Take a backup first. See https://www.zadran.net/disclaimer # # Destructive steps are left commented out on purpose -- uncomment them # only once you have understood what they do. # # If Windows will not run this file: a script saved from a browser is # marked as downloaded, and the RemoteSigned policy (the Windows Server # default) refuses it until you run Unblock-File .\enterprise-endpoint-management-sccm-homelab.ps1 # Where the policy is Restricted (the Windows 10 and 11 default), run it as # powershell -ExecutionPolicy Bypass -File .\enterprise-endpoint-management-sccm-homelab.ps1 $ErrorActionPreference = 'Stop' # ---- Set these for your environment ---- # The fully qualified name of your Configuration Manager site server. $SITESERVER = 'cm01.YourDomain.com' # The NetBIOS name of the same server. $SERVERNAME = 'CM01' # The three-character site code you chose during setup. $SITECODE = 'P01' # The short form of your domain name, used before the backslash in account names. $NETBIOS = 'YourDomain' # The account you run the Configuration Manager console as. $ADMINUSER = 'admin' # Your domain written as an LDAP path: yourdomain.com is DC=YourDomain,DC=com. $DOMAIN_DN = 'DC=YourDomain,DC=com' # Also read after --% below, where only environment variables expand. $env:DOMAIN_DN = $DOMAIN_DN $env:NETBIOS = $NETBIOS $env:SERVERNAME = $SERVERNAME dsacls --% "CN=System Management,CN=System,%DOMAIN_DN%" /I:T /G %NETBIOS%\%SERVERNAME%$:GA Get-ItemProperty 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots' | Select-Object KitsRoot10 setspn -L $SERVERNAME Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\SMS\Setup' | Select-Object 'Full Version' Get-Service SMS_EXECUTIVE, SMS_SITE_COMPONENT_MANAGER, SMS_NOTIFICATION_SERVER, MSSQLSERVER, W3SVC | Select-Object Name, Status Grant-SmbShareAccess -Name 'Sources$' -AccountName 'NT AUTHORITY\SYSTEM' -AccessRight Read -Force $a = New-ScheduledTaskAction -Execute 'cmd.exe' ` -Argument "/c dir `"\\${SITESERVER}\Sources`$\Applications`" > C:\systest.txt 2>&1" $p = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest Register-ScheduledTask -TaskName SysTest -Action $a -Principal $p -Force | Out-Null Start-ScheduledTask -TaskName SysTest; Start-Sleep 6; Get-Content C:\systest.txt Unregister-ScheduledTask -TaskName SysTest -Confirm:$false Install-WindowsFeature UpdateServices-Services,UpdateServices-DB -IncludeManagementTools cd "C:\Program Files\Update Services\Tools" .\wsusutil.exe postinstall SQL_INSTANCE_NAME="${SERVERNAME}" CONTENT_DIR=E:\WSUS Import-Module WebAdministration Set-ItemProperty 'IIS:\AppPools\WsusPool' -Name recycling.periodicRestart.privateMemory -Value 0 Set-ItemProperty 'IIS:\AppPools\WsusPool' -Name queueLength -Value 2000 Restart-WebAppPool -Name WsusPool New-NetFirewallRule -DisplayName "WSUS HTTP 8530" -Direction Inbound -Protocol TCP -LocalPort 8530 -Action Allow New-NetFirewallRule -DisplayName "WSUS HTTPS 8531" -Direction Inbound -Protocol TCP -LocalPort 8531 -Action Allow & "$env:ProgramFiles\Windows Defender\MpCmdRun.exe" -RemoveDefinitions -All Get-MpComputerStatus | Select-Object AntivirusSignatureVersion Get-GPO -All | ForEach-Object { $r = Get-GPOReport -Guid $_.Id -ReportType Xml if ($r -match 'WUServer|WindowsUpdate') { $_.DisplayName } } Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' | Select-Object WUServer, DoNotConnectToWindowsUpdateInternetLocations, DisableDualScan Get-MpPreference | Select-Object SignatureFallbackOrder Get-WmiObject -Namespace root\ccm\SoftwareUpdates\UpdatesStore -Class CCM_UpdateStatus | Where-Object { $_.Status -eq 'Missing' } | Select-Object Article, Title, Status | Format-Table -AutoSize Set-ItemProperty "$src\OSD\Images\Win11\install.wim" -Name IsReadOnly -Value $false Get-WindowsImage -ImagePath "$src\OSD\Images\Win11\install.wim" | Select-Object ImageIndex, ImageName | Format-Table -AutoSize Dism /Export-Image /SourceImageFile:"$src\OSD\Images\Win11\install.wim" ` /SourceIndex:6 /DestinationImageFile:"$src\OSD\Images\Win11-Pro\install.wim" ` /Compress:max /CheckIntegrity Grant-SmbShareAccess -Name 'Sources$' -AccountName "${NETBIOS}\${ADMINUSER}" -AccessRight Change -Force $CMLogs = Join-Path (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\SMS\Identification')."Installation Directory" 'Logs' Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' | Select-Object WUServer, DoNotConnectToWindowsUpdateInternetLocations, DisableDualScan @(Get-WmiObject -Namespace root\ccm\Policy\Machine\ActualConfig -Class CCM_UpdateCMAssignment).Count Get-WmiObject -Namespace root\ccm\SoftwareUpdates\UpdatesStore -Class CCM_UpdateStatus | Group-Object Status | Select-Object Name, Count ([wmiclass]'root\ccm:SMS_Client').TriggerSchedule('{00000000-0000-0000-0000-000000000021}') # Machine policy ([wmiclass]'root\ccm:SMS_Client').TriggerSchedule('{00000000-0000-0000-0000-000000000113}') # Software update scan ([wmiclass]'root\ccm:SMS_Client').TriggerSchedule('{00000000-0000-0000-0000-000000000108}') # Update deployment evaluation ([wmiclass]'root\ccm:SMS_Client').TriggerSchedule('{00000000-0000-0000-0000-000000000121}') # Application deployment evaluation Import-Module "$($env:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" Set-Location ${SITECODE}: