Skip to content

About

Two-tier software deployment via GPO on Windows Server 2022 — baseline MSIs to all workstations and per-request approved programs via security group filtering. Scoped through a dedicated Workstations OU. Demonstrates design iteration from domain-root linking to OU-based scoping.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

GPO Software Deployment — MYLAB.LOCAL

Two-tier software deployment model using Group Policy: baseline MSIs that install on every domain workstation, plus per-request approved programs filtered by computer security group membership. Scoped via a dedicated Workstations OU rather than linked at the domain root. End-to-end working deployment of five applications — 7-Zip, Chrome, VLC (baseline), PuTTY, and Wireshark (approved) — verified on a domain-joined Windows 11 client.

What this project demonstrates

  • Two-tier deployment design: baseline (all workstations) vs approved (per-request via security groups)
  • OU-based GPO scoping — workstation-targeted policies linked to a dedicated Workstations OU rather than the domain root
  • Share and NTFS permission layering for a deployment share (Domain Computers, Authenticated Users, Domain Admins)
  • GPO Software Installation with MSI packages, UNC path requirements, and Assigned deployment
  • Security filtering mechanics — including the Authenticated Users Read-on-Delegation requirement when restricting Security Filtering to a specific group
  • Event Viewer troubleshooting (Event 6035 — Software Installation deferred processing and the two-restart requirement)
  • Real-world limitations honestly documented — MSI-only constraint, Wireshark's Npcap dependency, and when to migrate to Intune or SCCM
  • Design iteration — refactoring from domain-root linking + DC Deny exclusion to OU-scoped linking

Lab environment

Component Detail
Domain controller WS2022.mylab.local (Windows Server 2022 Datacenter)
Client WIN11-TEST01 (Windows 11 Pro, domain-joined, in Workstations OU)
Platform VMware Workstation
Domain mylab.local
Deployment share \\WS2022\SoftwareDeploy$ (on DC E:\Software Deploy)
Baseline MSIs deployed 7-Zip 26.00, Google Chrome 147.0, VLC 3.0
Approved MSIs deployed PuTTY 0.83, Wireshark 4.6.4

Overview

This lab deploys software to domain-joined workstations via Group Policy using two distinct patterns:

Baseline deployment — software every workstation should have (archivers, media players, browsers). One GPO, linked to the Workstations OU, filtered to Authenticated Users.

Approved program deployment — specialist or per-request software (PuTTY for admin teams, Wireshark for network analysts). Each application gets its own GPO plus its own security group. Computers are added to the group as requests come in.

Both tiers are linked at the Workstations OU, not the domain root. The DC sits in its own Domain Controllers OU and is naturally out of scope — no explicit Deny exclusions required.

Folder structure on the DC

E:\Software Deploy\
├── Baseline\              ← MSIs that go on every workstation
└── Approved Programs\     ← MSIs deployed per-request via security groups

Naming convention

Type GPO Name Security Group Security Filter
Baseline SW-Baseline-AllPCs — Authenticated Users
Approved SW-[AppName]-Approved SW-[AppName] SW-[AppName] group

Part 1 — Shared folder setup (one-time)

All GPOs reference this same share. Set it up once.

1.1 Create the folder structure on the DC

On the DC, create E:\Software Deploy\ with Baseline\ and Approved Programs\ subfolders.

1.2 Share the folder

  1. Right-click E:\Software Deploy → Properties → Sharing tab.
  2. Click Advanced Sharing → tick Share this folder.
  3. Set share name to SoftwareDeploy$ (the $ hides it from casual network browsing).

Share name vs folder name: The folder on disk is E:\Software Deploy (with a space) but the share name is SoftwareDeploy$ (no space). All UNC paths use the share name, not the folder name. Clients never see or care about the folder name on the E: drive.

1.3 Set share permissions

Click Permissions. Remove Everyone, then add:

Principal Permission
Domain Computers Read
Domain Admins Full Control

Folder sharing configuration

Why Domain Computers and not individual PCs? Domain Computers is a built-in group that automatically includes every computer that joins the domain. Adding individual computer objects (e.g., WIN11-TEST01$) doesn't scale — you'd have to add every new PC manually.

Why Read, not Change? Clients only need to pull MSI files during installation. They never write back to this share. Change would be excessive.

1.4 Set NTFS permissions

Right-click E:\Software Deploy → Properties → Security tab → Edit.

Principal Permission
Authenticated Users Read & Execute
Domain Admins Full Control

NTFS security configuration

Verify inheritance to subfolders

The permissions set on E:\Software Deploy need to cascade to Baseline and Approved Programs.

  1. Navigate into E:\Software Deploy\Baseline → right-click → Properties → Security → Advanced.
  2. In the permissions list, confirm Authenticated Users and Domain Admins appear with Inherited from showing E:\Software Deploy.
  3. At the bottom, confirm Include inheritable permissions from this object's parent is ticked.
  4. Cancel (no changes needed). Repeat on Approved Programs.

If inheritance is disabled, click Enable inheritance → choose Convert when prompted → Apply.

What inheritance means here: Any permission set on E:\Software Deploy automatically cascades to every subfolder and file inside it. Baseline and Approved Programs don't need permissions configured separately — they inherit from the parent.

1.5 Place MSI files in the correct subfolder

Software type Location
Baseline (7-Zip, VLC, Chrome, etc.) E:\Software Deploy\Baseline\
Approved (PuTTY, Wireshark, etc.) E:\Software Deploy\Approved Programs\

MSI files staged in the Baseline folder

Critical — MSI only: GPO Software Installation only works with .msi files. .exe installers are silently ignored. Always download the MSI version from the vendor's website where available. Many commercial vendors do not publish public MSI installers; see the "Real-world limitations" section below for how this is handled in practice.

1.6 Test share access from the client BEFORE creating any GPO

On the client, open CMD and run:

dir \\WS2022\SoftwareDeploy$\Baseline
dir "\\WS2022\SoftwareDeploy$\Approved Programs"

Both must return MSI files successfully. If either fails, the GPO will never work — fix share or NTFS permissions before proceeding.


Part 2 — OU structure for deployment scoping

Before building the deployment GPOs, the OU structure needs two dedicated OUs: one for workstation computer objects, one for the security groups used in approved program filtering. This structure determines where GPOs are linked and how they're scoped.

2.1 Create the Workstations OU

  1. Open Active Directory Users and Computers (dsa.msc).
  2. Right-click mylab.local → New → Organizational Unit.
  3. Name it Workstations OU.
  4. Move WIN11-TEST01 from the default Computers container into this new OU.

Workstations OU containing WIN11-TEST01

2.2 Create the Software Groups OU

  1. Right-click mylab.local → New → Organizational Unit.
  2. Name it Software Groups.
  3. Inside it, create two Global Security groups: SW-PuTTY and SW-Wireshark. Don't add members yet.

Software Groups OU containing SW-PuTTY and SW-Wireshark

Why separate OUs for workstations and software groups? Keeping computer objects and security groups in different OUs makes delegation cleaner later — helpdesk staff can be given rights to manage security group memberships without touching computer objects, and vice versa. In a larger environment you'd also have separate OUs for servers, service accounts, and admin accounts following a tiered admin model.

2.3 Why OU-scoped linking beats domain-root linking

All workstation-targeted deployment GPOs are linked to the Workstations OU, not the domain root. This design decision is driven by three practical concerns:

Cleaner GPMC view. At 10+ approved programs, linking each GPO to the domain root creates a wall of text under mylab.local. Clicking on the domain root in GPMC should show policies that genuinely apply domain-wide (firewall baseline, password policy) — not a crowded list of workstation-specific software GPOs.

No DC exclusion needed. When GPOs are linked at the domain root, every computer in the domain is in scope by default — including the DC. Workstation software has no business on a DC, so an explicit Deny on Apply group policy for WS2022$ was required on every new GPO. Easy to forget, and a forgotten Deny means the DC accidentally receives workstation software. With OU-scoped linking, the DC sits in its own Domain Controllers OU and is naturally out of scope.

Scoping through structure, not exceptions. Expressing "this policy applies to workstations" through OU placement is cleaner than expressing it through Security Filtering plus Deny entries. The intent is visible from the GPMC tree, not buried in a GPO's Delegation tab.

See the Design iteration section at the end of this README for the original domain-root design and how it was refactored.


Part 3 — Baseline deployment (all workstations)

For software every workstation should have. One GPO can contain multiple MSI packages.

3.1 Create and link the GPO

  1. In GPMC, right-click the Workstations OU → Create a GPO in this domain, and Link it here.
  2. Name it SW-Baseline-AllPCs.

3.2 Add MSI packages

  1. Right-click SW-Baseline-AllPCs → Edit.
  2. Navigate to: Computer Configuration → Policies → Software Settings → Software Installation.
  3. Right-click in the right pane → New → Package.
  4. In the file dialog, type the UNC path directly:
\\WS2022\SoftwareDeploy$\Baseline\7z2301-x64.msi
  1. When prompted, select Assigned → OK.
  2. Repeat for each baseline MSI (Chrome, VLC, etc.). All go into this one GPO.

Baseline GPO with assigned MSI packages

Critical — UNC path only: Do NOT browse via C:\ or E:\. You must use the UNC path (\\servername\sharename\...). If you use a local path, the GPO stores that local path and the client will look for the file on its own hard drive — which doesn't exist. This is the single most common cause of software deployment failures.

Assigned vs Published: Assigned = installs automatically at computer startup. Published = shows up in "Add or Remove Programs" for users to install optionally (user-assigned only). Baseline deployments are always Assigned.

3.3 Verify security filtering

Under the Scope tab, Security Filtering should show Authenticated Users. Leave as is — combined with the OU link, this ensures every computer in the Workstations OU processes this GPO.

3.4 Final Workstations OU GPO layout

After both tiers are built (this section plus Part 4), the Workstations OU should have all deployment GPOs linked:

Workstations OU with all deployment GPOs linked


Part 4 — Approved programs deployment (per-request)

For specialist software that only specific workstations should receive. Each approved application gets its own GPO and its own security group. This section walks through PuTTY end-to-end; Wireshark follows the identical pattern.

4.1 Create and link the PuTTY GPO

  1. In GPMC, right-click the Workstations OU → Create a GPO in this domain, and Link it here.
  2. Name it SW-PuTTY-Approved.

4.2 Add the MSI package

  1. Right-click SW-PuTTY-Approved → Edit.
  2. Navigate to: Computer Configuration → Policies → Software Settings → Software Installation.
  3. New → Package → UNC path:
\\WS2022\SoftwareDeploy$\Approved Programs\PuTTY.msi
  1. Select Assigned → OK.

PuTTY package assigned in the GPO

4.3 Restrict the GPO to the security group

This is the key difference from baseline deployment.

  1. In GPMC, click on SW-PuTTY-Approved under the Workstations OU.
  2. Under the Scope tab → Security Filtering:
    • Select Authenticated Users → Remove.
    • Click Add → type SW-PuTTY → Check Names → OK.

Security Filtering restricted to SW-PuTTY

4.4 Re-add Authenticated Users with Read on Delegation

When Authenticated Users is removed from Security Filtering, it is also removed from Delegation entirely. This must be added back with Read-only permission — otherwise the GPO fails silently.

  1. Go to the Delegation tab → click Add.
  2. Type Authenticated Users → Check Names → OK.
  3. In the Permissions dropdown, select Read (not Edit settings).
  4. Click OK.

Authenticated Users added back with Read-only permission

Why keep Authenticated Users with Read in Delegation? If Authenticated Users has no permission at all on the GPO, computers can't read the GPO to determine whether they should apply it. The GPO becomes invisible to all machines and fails silently — no event, no error, no deployment. Authenticated Users needs Read so every computer can discover the GPO; only members of SW-PuTTY actually apply it. This is the most commonly misunderstood part of security filtering, and was reinforced by MS16-072 which changed how GPO reads are authenticated. Every approved program GPO needs this check.

4.5 Repeat for Wireshark

Same pattern as 4.1 through 4.4, with these substitutions:

  • GPO name: SW-Wireshark-Approved
  • MSI path: \\WS2022\SoftwareDeploy$\Approved Programs\Wireshark.msi
  • Security Filtering group: SW-Wireshark

4.6 Assign the client to both security groups

  1. In ADUC, find WIN11-TEST01 → right-click → Properties → Member Of tab → Add.
  2. Click Object Types → tick Computers → OK. (Easy to miss — by default Computers object type isn't selected, so typing a computer name fails with "object not found" until this is enabled.)
  3. Type SW-PuTTY → Check Names → OK.
  4. Repeat: Add → type SW-Wireshark → OK.

WIN11-TEST01 is a member of both approved program security groups

4.7 Deploy

  1. Restart the client — twice. See the troubleshooting section below for why.
  2. After login, open Programs and Features. All five applications should appear.

4.8 Verify GPO application

From an elevated CMD:

gpresult /r

Under Computer Settings → Applied Group Policy Objects, all three software GPOs should be listed alongside Firewall Baseline and Default Domain Policy.

gpresult showing all three software GPOs applied

And Programs and Features on the client:

Programs and Features showing all five deployed applications

4.9 Adding further approved programs

Each new approved application follows the same pattern:

Security Group GPO Name MSI
SW-PuTTY SW-PuTTY-Approved PuTTY.msi
SW-Wireshark SW-Wireshark-Approved Wireshark.msi
SW-[NewApp] SW-[NewApp]-Approved [NewApp].msi

To deploy a new app on a workstation: add the computer object to the relevant security group and restart twice.


Troubleshooting and real-world limitations

GPO is Applied in gpresult but software isn't installed — Event 6035

The most common "it's not working" scenario. gpresult /r shows the GPO under Applied Group Policy Objects, but Programs and Features doesn't show the software.

Cause: Windows uses fast logon optimisation by default — Group Policy processes asynchronously at boot so users can log in quickly. But Software Installation requires synchronous foreground processing because it must run before any user session exists. When a new Software Installation policy is detected, Windows defers the actual install until the next synchronous foreground boot.

Evidence: Event Viewer → Applications and Services Logs → Microsoft → Windows → GroupPolicy → Operational → Event ID 6035: "Software Installation Extension deferred processing until next synchronous foreground."

Event 6035 confirming deferred processing

Fix: Restart the client a second time. The software installs before login on the second boot.

Prevention for future deployments: Enable Computer Configuration → Policies → Administrative Templates → System → Logon → Always wait for the network at computer startup and logon in a machine-baseline GPO. This forces synchronous foreground processing every boot, so Software Installation policies install on the first boot after policy changes. Trade-off: slightly slower boot times because the machine waits for the domain to be contactable before showing the login screen. Standard practice in enterprise environments.

Software doesn't appear after restart (general troubleshooting)

Work through these in order:

1. Did you use the UNC path? Check the package properties inside the GPO. Source path must start with \\WS2022\SoftwareDeploy$\... — not C:\ or E:\. Number one failure cause.

2. Is it actually an MSI? GPO Software Installation only supports .msi files. .exe installers are silently ignored.

3. Can the client reach the share? From an admin CMD on the client: dir "\\WS2022\SoftwareDeploy$\Approved Programs". If this fails, it's a share permission, NTFS permission, DNS, or firewall issue.

4. Is the GPO applied? gpresult /r. Check under Computer Settings → Applied Group Policy Objects. If not listed, check the "filtered out" section for the reason. Common causes: computer not in the right security group, Authenticated Users missing Read on Delegation, WMI filter blocking it.

5. Check Event Viewer. Applications and Services Logs → Microsoft → Windows → GroupPolicy → Operational. Look for the most recent boot. Common errors:

  • Event 6035 — Deferred processing. Restart again.
  • Event 101 — Failed to access the GPO. Share permission or DNS issue.
  • Software Installation errors — Usually corrupt MSI or UNC path issue.

6. Group membership refreshes at boot. After adding a computer to a security group, the computer needs to restart to pick up the new group membership. gpupdate /force alone won't refresh the Kerberos ticket that carries group memberships.

Wireshark installs but can't capture live traffic

Cause: Wireshark requires Npcap (packet capture driver) for live traffic capture. The Wireshark EXE installer bundles Npcap and installs it interactively. The MSI installer — which is what GPO Software Installation requires — does not install Npcap. Wireshark opens and can read existing .pcap files, but the interface list is empty for live capture.

Why not deploy Npcap via GPO too? Npcap ships as an EXE-only installer from Nmap Project. GPO Software Installation cannot deploy EXE installers. Free Npcap is also capped at 5 systems per the licence.

Practical handling options:

  • Lab / small deployment: Install Npcap manually on each workstation that needs live capture. Documented as a known limitation.
  • GPO startup script: Deploy Npcap via a computer startup script calling npcap.exe /S for silent install. Works but sits outside GPO Software Installation's management model.
  • Enterprise: Move Wireshark deployment to Intune Win32 apps or SCCM Application model, where both the MSI and its EXE-based Npcap dependency can be packaged together (typically using PSAppDeployToolkit wrapping).

This limitation is representative of the broader problem outlined below.

When to migrate off GPO Software Installation

GPO Software Installation is a valid tool for basic MSI-based baseline deployment in small AD environments. At scale, it hits ceilings:

  • MSI-only. Many commercial vendors ship EXE installers (Adobe, Autodesk) or have dependencies that ship as EXE (like Wireshark's Npcap). GPO Software Installation cannot handle these without supplementary startup scripts.
  • GPMC sprawl. At 10+ approved programs, even with OU-scoping, GPMC lacks folder or grouping features for GPOs. The naming convention (SW-[App]-Approved) helps alphabetical sorting, but visibility remains limited.
  • No supersedence, dependencies, or maintenance windows. Assigned MSIs install at boot with no staging, no dependency resolution, no rollback, and no way to target a maintenance window.
  • Poor observability. Failure modes are visible only through Event Viewer on each client. No central reporting.

Modern enterprise alternatives:

  • Intune Win32 apps — each application is a discrete object in a catalogue, assigned via Entra ID groups. Handles MSI, EXE, PowerShell scripts, complex detection logic, and per-user or per-device targeting. Works over the internet without VPN. Where most organisations with Microsoft 365 are heading.
  • SCCM Application model — on-prem enterprise standard. Proper application catalogue with supersedence, dependencies, maintenance windows, and central deployment reporting.
  • PSAppDeployToolkit (PSADT) — PowerShell framework for wrapping EXE installers with logging, user UI, and proper exit code handling. Commonly used inside SCCM or Intune packages.

In a production environment with more than a handful of applications, the deployment pattern demonstrated in this lab would typically be used only for foundational baseline software, with everything else managed through Intune or SCCM.


Design iteration — original design and refactor

This repo went through one significant design iteration worth documenting. The original design worked but didn't scale; the refactor fixes the scaling problem and simplifies the scoping model.

Original design

All software deployment GPOs linked at the domain root (mylab.local). Baseline scoped to every domain-joined computer, with the DC explicitly excluded via Deny on Apply group policy on the WS2022$ computer object in the GPO's Delegation tab.

Original design — DC excluded via Deny on Apply group policy

Why this worked but needed refactoring

Functionally correct — Deny overrides Allow, so the DC was successfully excluded from baseline software. But the design surfaced problems:

  • Domain root clutter. Every new approved program GPO added another link under mylab.local. At 10+ approved programs, the domain root becomes a wall of text in GPMC, mixing workstation-specific software with genuinely domain-wide policies like firewall and password baselines.
  • Deny exclusion was fragile. Each new workstation-targeted GPO required remembering to add the DC Deny entry. Forgetting it meant the DC would receive workstation software — a real risk in larger environments where server admins and workstation admins might be different people.
  • Scoping expressed through exceptions, not structure. "This policy applies to workstations only" was encoded in a Security Filtering exception rather than an OU boundary. The intent was hidden in the Delegation tab rather than visible in the GPMC tree.

Refactor

  1. Created a Workstations OU at the domain root.
  2. Moved WIN11-TEST01 from the default Computers container into the Workstations OU.
  3. Unlinked SW-Baseline-AllPCs and Windows Update Settings from the domain root.
  4. Re-linked both to the Workstations OU.
  5. New approved program GPOs (SW-PuTTY-Approved, SW-Wireshark-Approved) created directly under the Workstations OU.
  6. Removed the DC Deny entry from SW-Baseline-AllPCs — no longer needed, since the DC sits in the Domain Controllers OU and is naturally out of scope.

The domain root now shows only truly domain-wide policies: Default Domain Policy, Firewall Baseline. All workstation-specific deployment GPOs live under the Workstations OU where they belong.


Quick reference — day-to-day operations

Adding a new baseline app

  1. Drop the MSI into E:\Software Deploy\Baseline\ on the DC.
  2. Edit SW-Baseline-AllPCs GPO → Software Installation → New → Package → UNC path.
  3. All workstations install it at their next second-boot-after-change.

Adding a new approved program

  1. Drop the MSI into E:\Software Deploy\Approved Programs\ on the DC.
  2. Create security group SW-[AppName] in the Software Groups OU.
  3. Create GPO SW-[AppName]-Approved linked to the Workstations OU.
  4. Add the MSI under Software Installation.
  5. In Security Filtering, replace Authenticated Users with SW-[AppName].
  6. In Delegation, add Authenticated Users back with Read permission.
  7. Add target computer objects to SW-[AppName].
  8. Restart target workstations (twice — see troubleshooting).

Removing software from a workstation

For approved programs: remove the computer object from the security group and restart. Depending on the GPO package's Deployment tab options, the software may be automatically uninstalled on next boot.

Removing a baseline app entirely

Edit SW-Baseline-AllPCs → Software Installation → right-click the package → All Tasks → Remove. Choose whether to immediately uninstall from all workstations or allow users to continue using it.


Key concepts reinforced in this build

Concept Where it appears
Two-tier deployment model Baseline (all workstations) vs Approved (per-request via security groups)
OU-based scoping through structure All deployment GPOs linked to Workstations OU rather than domain root
Share vs NTFS permission layering Domain Computers Read on share, Authenticated Users R&E on NTFS
UNC path dependency GPO stores whatever path you enter — local paths fail silently on clients
Computer-assigned software runs at boot Restart required, not gpupdate /force
Two-restart requirement Software Installation defers to next synchronous foreground boot (Event 6035)
Security filtering mechanics Authenticated Users needs Read on Delegation even when removed from Security Filtering
Group membership refreshes at boot Adding a computer to a security group requires restart to take effect
MSI-only limitation .exe installers silently ignored; workarounds via startup scripts or modern tooling
Design iteration Refactored from domain-root linking + DC Deny to OU-scoped linking
When to move beyond GPO Intune Win32 apps or SCCM for EXE handling, supersedence, reporting, and scale

About

Two-tier software deployment via GPO on Windows Server 2022 — baseline MSIs to all workstations and per-request approved programs via security group filtering. Scoped through a dedicated Workstations OU. Demonstrates design iteration from domain-root linking to OU-based scoping.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors