This week I spent some time setting up automated patching for a Windows EC2 instance using AWS Systems Manager (SSM), and it turned out to be much simpler than I expected. Once the core pieces are in place, patching becomes a repeatable, low-touch process instead of a manual chore.
Getting the Windows Instance Ready
I started with a standard Windows Server instance built via Terraform. Modern AWS Windows AMIs already include the SSM Agent, so the main things I needed were:
- An IAM instance profile with the
AmazonSSMManagedInstanceCorepolicy. - Network access so the instance can reach SSM endpoints (in my case, via a public subnet).
As soon as the instance booted with the correct IAM role attached, it appeared in the Systems Manager console as a managed instance. That was the first confirmation that the patching pipeline could work without me ever logging in via RDP.
Making the Instance “Patch Aware”
The next step was tagging the instance so Patch Manager knows how to treat it. I used environment tags and a different patching schedule for each environment, so Nonprod and Staging are updated before Prod. This lets me group instances logically and apply different patching waves per environment.
In Terraform, I created an SSM patch baseline for Windows that:
- Targets the Windows Server product I care about (for example, Windows Server 2025).
- Includes Critical and Important security updates, plus key update classifications.
- Globally excludes low severity updates to reduce noise.
Each patch group value is then registered against this baseline. That way, when SSM looks at
an instance with Patch Group = Nonprod, it knows exactly which rules and
approvals to apply.
Separating Scan and Install
To make patching safer and more observable, I split the process into two phases:
- Scan to identify which patches are missing.
- Install will apply the approved patches during a controlled window.
For the scan phase, I used an SSM Association with the AWS-RunPatchBaseline
document in Scan mode. This runs on a schedule and updates compliance information,
so I can see exactly what is pending before anything changes on the server.
For installs, I set up an SSM Maintenance Window. Each patch wave
(non-prod, staging, prod) has its own schedule, all driven by the same
Patch Group tags. Inside that window, a maintenance window task runs
AWS-RunPatchBaseline with Operation = Install, so patches are
only applied within that defined time frame.
What Surprised Me
The biggest surprise was how little “custom scripting” I actually needed. Once the building blocks were in place (SSM-managed instance, patch group tags, patch baseline, and maintenance windows) everything else was configuration:
- No logging into Windows Update manually.
- No one-off PowerShell scripts to maintain for every server.
- A single Terraform-defined pattern that can be reused for any new Windows instance.
Adding a new Windows EC2 instance to the patching process is now as simple as applying the
correct Patch Group tag and letting Systems Manager do its job.