Windows Software Deployment without SCCM: Chocolatey and Ansible
Fabian Peter 10 Minuten Lesezeit

Windows Software Deployment without SCCM: Chocolatey and Ansible

Windows Software Deployment without SCCM: Chocolatey and Ansible with Polycrate
Ganze Serie lesen (24 Artikel)

Diese Serie zeigt Schritt für Schritt, wie Ansible mit Polycrate zu einer strukturierten, teilbaren und compliance-fähigen Automatisierungsplattform wird – von den Grundlagen bis zu Enterprise-Szenarien.

  1. Install Polycrate and Build Your First Ansible Block in 15 Minutes
  2. Blocks, Actions, and Workspaces: The Modular Principle of Polycrate
  3. Linux Servers on Autopilot: System Management with Polycrate and Ansible
  4. Nginx and Let's Encrypt as a Reusable Polycrate Block
  5. Managing Docker Stacks on Linux Servers with Polycrate
  6. Many Servers, One Truth: Multi-Server Management with Polycrate Inventories
  7. Windows Automation with Polycrate: Ansible and WinRM Without Pain
  8. Windows Software Deployment without SCCM: Chocolatey and Ansible
  9. Hybrid Automation: Windows and Linux in the Same Polycrate Workspace
  10. Deploy Kubernetes Apps from the PolyHub: From Idea to Deployment in Minutes
  11. Creating Your Own Kubernetes App as a Polycrate Block: A Step-by-Step Guide
  12. Multi-Cluster Kubernetes with Polycrate: Why One Cluster, One Workspace
  13. SSH Sessions and kubectl Debugging: Polycrate as an Operations Tool
  14. Helm Charts as a Polycrate Block: More Control Over Chart Deployments
  15. Policy as Code: Automating Compliance Requirements with Polycrate
  16. Workspace Encryption: Managing Secrets in GDPR Compliance – Without External Tooling
  17. Managing Raspberry Pi and Edge Nodes with Polycrate in IoT and Edge Computing
  18. Enterprise Automation: Building, Versioning, and Sharing Blocks Within Teams
  19. Polycrate MCP: Connecting AI Assistants with Live Infrastructure Context
  20. Polycrate vs. plain Ansible: What You Gain – and Why It's Worth It
  21. The Polycrate Ecosystem: PolyHub, API, MCP, and the Future of Automation
  22. Your First Productive Polycrate Workspace: A Checklist for Getting Started
  23. Auditable Operations: SSH Sessions and CLI Activities with Polycrate API
  24. Polycrate API for Teams: Centralized Monitoring and Remote Triggering

TL;DR

  • You can implement standardized Windows software deployment without expensive SCCM infrastructure – using Chocolatey as a package manager and Ansible as the control center.
  • Polycrate packages Ansible, Python, and the entire toolchain into a container, solving the dependency problem and bringing structure to your automation through reusable blocks.
  • A software baseline is modeled as a Polycrate block: Office, Developer, and Server profiles are versioned, reproducible, and executable via polycrate run – without a local Ansible installation.
  • Through groups in the inventory, you can implement a rolling rollout: first test workstations, then broad deployment into production.
  • ayedo supports teams in modeling such scenarios in a practical software deployment workshop and sustainably bringing them into operation.

The SCCM Problem: When Overhead Outweighs Benefits

Many Windows admins know the dilemma: Microsoft Endpoint Configuration Manager (formerly SCCM) is powerful, but:

  • Licensing costs are high – particularly hard to justify for small and medium environments.
  • The infrastructure is complex (SQL Server, Site Server, distribution points).
  • Changes require long lead times because everything must be “properly” modeled in SCCM first.
  • Scripts and small automation components disappear in the GUI or in individual scripts and are hard to version.

At the same time, the need is clear:

  • Standard software like 7-Zip, browsers, PDF viewers, admin tools.
  • Different baselines: Office users vs. developers vs. servers.
  • Reproducibility: A new machine should be at the same state as existing ones in 30–60 minutes.

This is where Chocolatey, Ansible, and Polycrate form an exciting combination: You achieve many of the benefits of SCCM (standardized, repeatable, auditable) without its costs and complexity.


Chocolatey as a Windows Package Manager

Chocolatey is – simply put – apt or yum for Windows:

  • Packages are installed from repositories (e.g., the public Chocolatey repository or an internal one).
  • Installation, update, and uninstallation are handled via a consistent CLI command (choco install, choco upgrade, choco uninstall).
  • Many standard tools are already available as ready-made packages: browsers, tools, runtime environments, etc.

For admins, this means:

  • No more manual MSI downloads and click installers.
  • Version pinning is trivial: choco install 7zip --version 22.1.0.
  • Packages are scriptable and thus ideal for Ansible.

Important: In production environments, you usually use an internal Chocolatey repository. The principle remains the same – only the source URL changes.


win_chocolatey in Ansible: Installing, Updating, Removing Packages

Ansible comes with its own module, win_chocolatey, which encapsulates exactly this Chocolatey functionality.

A minimal example playbook (without Polycrate, just for context):

- name: Windows Baseline with Chocolatey
  hosts: windows_office
  gather_facts: false

  tasks:
    - name: Ensure Chocolatey is installed
      ansible.windows.win_chocolatey:
        name: chocolatey
        state: present

    - name: Install 7zip
      ansible.windows.win_chocolatey:
        name: 7zip
        version: '22.1.0'
        state: present

    - name: Install Google Chrome
      ansible.windows.win_chocolatey:
        name: googlechrome
        version: '118.0.5993.90'
        state: present

With plain Ansible, this means for you:

  • You need a working Python and Ansible installation locally.
  • Everyone on the team must use compatible versions, otherwise “works on my machine” effects occur.
  • You must organize and document Ansible configuration (inventory, ansible.cfg, collections) yourself.

This is where Polycrate comes into play.


Why Polycrate Comes into Play

Polycrate does not replace Ansible – it provides a clean, reusable packaging for Ansible.

The relevant advantages in this scenario:

  1. Dependency Problem Solved

    • Ansible runs in a container provided by Polycrate.
    • No local Python chaos, no different Ansible versions in the team.
    • Additional tools (e.g., choco, pwsh, kubectl) are consistently added via a Dockerfile.poly or a setup script.
    • All colleagues use exactly the same toolchain – whether on a laptop, VDI, or terminal server.

    More on this in the Ansible Integration of Polycrate.

  2. Guardrails and Sharable Automation

    • Instead of individual playbooks, there are blocks that are clearly structured (with block.poly).
    • These blocks can be versioned and shared in an OCI registry.
    • A block registry.acme-corp.com/acme/windows/windows-software-baseline:0.1.0 is a “product” that your team can use, test, and share – internally or via the PolyHub.

    Best practices can be found under Polycrate Best Practices.

  3. Secure Configuration

    • License keys, internal repository URLs, or admin credentials are stored in the workspace and encrypted with polycrate workspace encrypt.
    • The built-in age encryption facilitates compliance without additional tooling.
    • Details on this: Workspace Encryption in Polycrate.

For you as a Windows admin, this means: You focus on the playbooks and software baselines – Polycrate takes care of the toolchain, structure, and reuse.


The Workspace: acme-corp-automation

We build an example for the fictional acme-corp.com:

  • Three target groups:
    • office-workstation
    • developer-workstation
    • server
  • Each with its own host groups in the Ansible inventory.
  • A shared software baseline as a Polycrate block.

A minimal inventory.yml in the workspace root might look like this:

all:
  hosts:
    win-office-01.acme-corp.com: {}
    win-office-10.acme-corp.com: {}
    win-dev-01.acme-corp.com: {}
    win-srv-01.acme-corp.com: {}

  children:
    windows_office_test:
      hosts:
        win-office-01.acme-corp.com:
      vars:
        ansible_user: Administrator
        ansible_connection: winrm
        ansible_winrm_server_cert_validation: ignore

    windows_office_prod:
      hosts:
        win-office-10.acme-corp.com:
      vars:
        ansible_user: Administrator
        ansible_connection: winrm
        ansible_winrm_server_cert_validation: ignore

    windows_developer:
      hosts:
        win-dev-01.acme-corp.com:
      vars:
        ansible_user: Administrator
        ansible_connection: winrm
        ansible_winrm_server_cert_validation: ignore

    windows_servers:
      hosts:
        win-srv-01.acme-corp.com:
      vars:
        ansible_user: Administrator
        ansible_connection: winrm
        ansible_winrm_server_cert_validation: ignore

No passwords in the inventory—set ansible_password in playbooks from secrets.poly / workspace.secrets.* (see Workspace encryption).

Polycrate automatically sets ANSIBLE_INVENTORY to this file. You don’t need an additional ansible.cfg.

Our workspace.poly defines which blocks exist:

name: acme-corp-automation
organization: acme

blocks:
  - name: windows-office-baseline
    from: registry.acme-corp.com/acme/windows/windows-software-baseline:0.1.0
    config:
      profile: office
      target_group: windows_office_test

  - name: windows-developer-baseline
    from: registry.acme-corp.com/acme/windows/windows-software-baseline:0.1.0
    config:
      base_profile: office
      profile: developer-extra
      target_group: windows_developer

  - name: windows-server-baseline
    from: registry.acme-corp.com/acme/windows/windows-software-baseline:0.1.0
    config:
      profile: server
      target_group: windows_servers
      allow_reboot: false

from: is the full OCI registry reference including the version tag; registry.acme-corp.com is a fictional example (not tied to a specific production registry).

Important:

  • All three entries use the same block version; unpacked it lives under blocks/registry.acme-corp.com/acme/windows/windows-software-baseline/.
  • Differences lie only in the configuration (profile, base_profile, etc.).
  • This already gives you a form of block inheritance through configuration: Developer “inherits” Office plus additional tools.

More on generic inheritance in Polycrate can be found in the documentation on Inheritance.


The Polycrate Block: name as full registry reference in block.poly

Now we define the block itself under blocks/registry.acme-corp.com/acme/windows/windows-software-baseline/block.poly (directory layout = registry path). In block.poly, name must be the full registry URL—the same string as from: in workspace.poly, without the version tag (no :0.1.0 suffix). In short: from: = name + : + tag. That is not the same identifier as the block instances in workspace.poly (windows-office-baseline, windows-developer-baseline, …).

# name = from: without tag (full registry path)
name: "registry.acme-corp.com/acme/windows/windows-software-baseline"
version: 0.1.0
kind: generic

config:
  chocolatey_source: "https://community.chocolatey.org/api/v2/"

  # Central definition of software profiles
  software_profiles:
    office:
      - name: 7zip
        version: "22.1.0"
      - name: googlechrome
        version: "118.0.5993.90"
      - name: sumatrapdf
        version: "3.4.6"

    developer-extra:
      - name: vscode
        version: "1.84.0"
      - name: git
        version: "2.44.0"
      - name: postman
        version: "10.21.0"

    server:
      - name: sysinternals
        version: "2023.9.23"
      - name: notepadplusplus
        version: "8.6.2"

actions:
  - name: baseline
    playbook: baseline.yml

A few points about this:

  • polycrate run windows-office-baseline … and similar commands use the instance name from workspace.poly, not the full registry reference in name (block.poly).
  • Version pinning: All packages have specific version specifications. latest would be more convenient, but you lose all reproducibility. Your goal: “A workstation in April 2026 looks the same as one in June – as long as you don’t intentionally increase the block version.”
  • The profiles office, developer-extra, and server are centrally defined. Workspace-specific, you only decide which profile is used.

Once this block runs stably, you can push it to your OCI registry—for example (fictional registry, same path scheme as above):

registry.acme-corp.com/acme/windows/windows-software-baseline:0.1.0

This makes your software baseline a sharable automation for other teams.


The Ansible Playbook: Combine and Deploy Profiles

Now we need the playbook blocks/registry.acme-corp.com/acme/windows/windows-software-baseline/baseline.yml, which uses Chocolatey and combines profiles:

- name: Windows Software Baseline with Chocolatey
  hosts: "{{ block.config.target_group }}"
  gather_facts: false

  vars:
    choco_source: "{{ block.config.chocolatey_source }}"
    base_profile_name: "{{ block.config.base_profile | default(None) }}"
    profile_name: "{{ block.config.profile }}"

  tasks:
    - name: Ensure Chocolatey is installed
      ansible.windows.win_chocolatey:
        name: chocolatey
        state: present

    - name: Load base packages (e.g., office)
      ansible.builtin.set_fact:
        base_packages: "{{ block.config.software_profiles[base_profile_name] | default([]) }}"

    - name: Load profile packages (e.g., developer-extra or server)
      ansible.builtin.set_fact:
        profile_packages: "{{ block.config.software_profiles[profile_name] }}"

    - name: Merge final list of packages
      ansible.builtin.set_fact:
        final_packages: "{{ base_packages + profile_packages }}"

    - name: Install/update all packages to desired version
      ansible.windows.win_chocolatey:
        name: "{{ item.name }}"
        version: "{{ item.version }}"
        state: present
        source: "{{ choco_source }}"
      loop: "{{ final_packages }}"

    - name: Optional: Allow reboot after installation
      ansible.windows.win_reboot:
        msg: "Reboot after baseline installation by Polycrate/Ansible"
        pre_reboot_delay: 60
      when: block.config.allow_reboot | default(true)

Important details:

  • hosts: "{{ block.config.target_group }}" ensures that you can control which host group is addressed per block instance – ideal for rolling rollouts.
  • base_profile and profile implement our configuration inheritance:
    • Office workstations use profile: office without base_profile.
    • Developer workstations use base_profile: office and profile: developer-extra—that is “developer inherits office plus extra tools”.
  • The ansible.windows.win_chocolatey and ansible.windows.win_reboot modules come from the Windows collections; Polycrate provides a suitable Ansible environment in the container.

With plain Ansible you would have to orchestrate all variable sources (e.g. group_vars, host_vars, extra_vars) and CLI calls yourself. With Polycrate, these parameters become part of the block and are versioned.


Rolling rollout: test group first, then production

The rolling rollout follows naturally from inventory groups:

  1. Define the test group

    In the inventory.yml above, windows_office_test and windows_office_prod exist. In workspace.poly, the office baseline’s target_group is initially windows_office_test.

  2. Run the baseline on the test group

    polycrate run windows-office-baseline baseline

    Polycrate:

    • Starts a container with Ansible and the required collections.
    • Loads the workspace (including inventory) into the container.
    • Runs baseline.yml with the parameters from windows-office-baseline.
  3. After tests: switch target to production

    Change workspace.poly:

    - name: windows-office-baseline
      from: registry.acme-corp.com/acme/windows/windows-software-baseline:0.1.0
      config:
        profile: office
        target_group: windows_office_prod

    Save the workspace and commit to Git—so you record from which workspace definition version the baseline rolled out to production.

  4. Roll out to production

    polycrate run windows-office-baseline baseline

You can bundle these steps in a Polycrate workflow later if you want. For many teams it is already a big win that test vs. production is clear from inventory groups and Git history.


Frequently asked questions

Do I need a central Chocolatey repository for this setup?

No—you can use the public Chocolatey repository as in the example (https://community.chocolatey.org/api/v2/). Many organizations still prefer an internal repository:

  • Control over which packages and versions are allowed.
  • Better reproducibility because you are not surprised by upstream changes.
  • Less reliance on external services (offline / restricted internet).

In the Polycrate block, the source is just a config variable (chocolatey_source); you can switch from public to internal without rewriting the playbook.

How does Polycrate help with compliance and audits?

Two points matter most:

  • Versioned blocks and workspaces: You can always see which block version (e.g. registry.acme-corp.com/acme/windows/windows-software-baseline:0.1.0) ran with which workspace configuration against which systems—supporting audit traceability.
  • Workspace encryption: Sensitive data such as credentials, license keys, or internal URLs can live in the workspace and be encrypted with polycrate workspace encrypt, which helps meet requirements from standards such as ISO 27001 or internal policies without an external secrets manager.

More in the documentation on workspace encryption.

How is this different from “Ansible only”—is Polycrate worth it?

Plain Ansible can implement everything in this article. The difference is everything around it:

  • You must standardize Ansible, Python, collections, inventory layout, and playbooks yourself and enforce them in the team.
  • Sharing automation is mostly Git repos, folder conventions, and docs—without a clear block/versioning model.
  • New colleagues need more setup time before everything works.

Polycrate adds:

  • A predefined Ansible toolchain container that is the same everywhere.
  • The block model as a guardrail against playbook sprawl.
  • Registry integration to distribute automation as reusable building blocks (e.g. via PolyHub).

In short: Polycrate pays off when you have more than a few ad-hoc playbooks and want automation as a “product” in the team.

More questions? See our FAQ


From theory to practice

With Chocolatey, Ansible, and Polycrate you have a practical path to Windows software deployment without SCCM infrastructure:

  • You have seen how a Windows software baseline is modeled as a Polycrate block—including clearly versioned package lists.
  • You use configuration to serve different targets (office, developer, server) from the same block and apply inheritance in daily use.
  • Modules such as win_chocolatey keep automation idempotent and traceable, while Polycrate handles the container toolchain, workspace structure, and reuse.
  • Rolling rollouts across test and production groups become a target_group change and a Git commit—not a new SCCM deployment.

We often see Windows teams start with building blocks like these and then add patch management, local admin groups, browser hardening, and combined workspaces for Linux, Windows, and edge environments.

If you want to walk through this approach in your environment—from the first workspace structure to a tested rollout to your test group—we are happy to join you in a shared software deployment workshop.

Ähnliche Artikel