Logo Desktop as a Service
Image Management

Image Management

June 18, 2025
7 min read
Table of Contents
index

From Manual Hell to Automated Heaven:

Building Citrix Master Images with Packer

It’s 3 AM, you’re manually configuring yet another Windows image, and you realize you forgot to install a critical patch three hours ago…

Sound familiar?

If you’re still building images by hand in 2025, you’re not just wasting tim, you’re creating technical debt that will haunt your team for years.

After years of manual image management, I finally broke free from this cycle of inefficiency.
Here’s how I transformed a painful, error-prone process into a streamlined automation pipeline using Packer and why you should too.

The Real Cost of Manual Image Management

Let’s be honest, manual image provisioning isn’t just slow, it’s a business risk.
Every hand-crafted image is a snowflake, impossible to reproduce consistently.
When your production environment fails at 2 AM, can you confidently rebuild that critical image in minutes, not hours?

The numbers don’t lie:

  • Manual image builds: 4-6 hours per new image
  • Automated builds: 45 minutes, completely unattended
  • Configuration drift: Eliminated
  • Human error: Virtually zero

Why Packer Changes Everything

Packer isn’t just another tool, it’s infrastructure as code for your golden images.
While your peers are still clicking through GUI wizards, you’ll be treating image builds like any other code deployment: versioned, tested, and repeatable.

Quick reality check: If you can’t rebuild your entire image infrastructure from a git repository, you’re doing it wrong.

Prerequisites: Get Your Foundation Right

Before we dive into the technical implementation, ensure you have:

  • Azure subscription with resource creation permissions
  • Packer installed (locally or on your CI/CD pipeline)
  • PowerShell proficiency for provisioning scripts
  • Basic Azure CLI knowledge for service principal management

Note: While I’m using Azure here, this approach works seamlessly with AWS, GCP, or on-premises environments. Azure just happens to be cost-effective for testing.

Setting Up Azure Authentication

Service Principal Configuration

First, we need a service principal for Packer authentication.

Terminal window
az login
az ad sp create-for-rbac --role Contributor --scopes /subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

Output:

{
"appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"displayName": "azure-cli-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"password": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

⚠️ Security Note: This example uses subscription-level Contributor permissions for simplicity.
In production, scope this down to specific resource groups. Your security team will thank you.

Resource Group Strategy

Smart infrastructure engineers separate build artifacts from production images:

Terminal window
# Production images - locked and protected
az group create --name CitrixAutomation --location westeurope
az lock create --name LockRGDelete --lock-type CanNotDelete --resource-group CitrixAutomation
# Build artifacts - ephemeral and disposable
az group create --name CitrixAutomation-Builder --location westeurope

This separation prevents accidental deletion of production images while allowing you to clean up build artifacts aggressively.

Package Management: Beyond the Basics

Why Chocolatey Wins for Windows Automation

While there are several package managers for Windows, Chocolatey stands out for infrastructure automation:

  • Declarative package management through packages.config
  • Version pinning for reproducible builds
  • Massive repository of pre-packaged software
  • Unattended installation capabilities

Here’s a production-ready packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="googlechrome" version="137.0.7151.69" />
<package id="vscode" version="1.100.3" packageParameters="/NoDesktopIcon" />
<package id="visualstudiocode-disableautoupdate" version="1.0.0.20180620" />
<package id="7zip.install" version="24.9.0"/>
<package id="notepadplusplus" version="8.6.9" />
<package id="git" version="2.47.1" />
</packages>

Pro tip: Always pin specific versions. “Latest” is the enemy of reproducible infrastructure.

Enterprise Alternative: SOFT2Go

For enterprise environments requiring advanced package management, I recommend SOFT2Go by Danoffice IT. It’s purpose-built for complex Windows environments and handles edge cases that generic package managers often struggle with.
And ohh yes, I work for Danoffice IT and think is an awesome product!

The Packer Template: Where Magic Happens

Here’s the production-ready Packer template that transforms hours of manual work into minutes of automated precision:

{
"builders": [{
"type": "azure-arm",
"client_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"client_secret": "---------------------------------------",
"tenant_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"subscription_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"managed_image_resource_group_name": "CitrixAutomation",
"managed_image_name": "CitrixMasterImage_{{isotime | clean_resource_name}}",
"os_type": "Windows",
"image_publisher": "MicrosoftWindowsDesktop",
"image_offer": "Windows-10",
"image_sku": "win10-22h2-avd-g2",
"communicator": "winrm",
"winrm_use_ssl": true,
"winrm_insecure": true,
"winrm_timeout": "5m",
"winrm_username": "packer",
"azure_tags": {
"Creation": "{{isotime | clean_resource_name}}",
"Software": "ba8b4b95-70b2-4509-bab6-e4f3ae746fa7",
"InitiatedBy": "SBJR",
"Environment": "Production",
"ManagedBy": "Packer"
},
"build_resource_group_name": "CitrixAutomation-Builder",
"vm_size": "Standard_D2ads_v6",
"license_type": "Windows_Client",
"shared_image_gallery_destination": {
"subscription": "ca6495c3-6c00-4fa8-a5a6-665804dfadc5",
"resource_group": "CitrixAutomation",
"gallery_name": "CitrixMasterImageGallery",
"image_name": "CitrixMasterImage",
"image_version": "1.0.0",
"replication_regions": [
"westeurope",
"northeurope"
]
}
}],
"provisioners": [{
"type": "powershell",
"inline": [
"# Install Chocolatey with modern security practices",
"Set-ExecutionPolicy Bypass -Scope Process -Force",
"[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072",
"iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))",
"# Download and install packages",
"Invoke-WebRequest https://urlToChoco -OutFile packages.config",
"choco feature enable -n allowGlobalConfirmation",
"choco install packages.config --timeout 0"
]
},
{
"type": "windows-restart"
},
{
"type": "powershell",
"inline": [
"# Wait for Azure services to be ready",
"while ((Get-Service RdAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
"while ((Get-Service WindowsAzureGuestAgent).Status -ne 'Running') { Start-Sleep -s 5 }",
"# Sysprep and prepare for imaging",
"& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit",
"while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10 } else { break } }"
]
}]
}

Execution: From Code to Infrastructure

Execute your automated image build with a single command:

Terminal window
packer build .\CitrixMasterImage.json

That’s it. No GUI clicking, no manual steps, no room for human error. Just reliable, repeatable infrastructure.

Build time: Approximately 45 minutes for a fully configured Citrix master image with all software packages installed.

What You’ve Actually Built

This isn’t just an image—it’s a paradigm shift. You’ve created:

  • Reproducible infrastructure that can be rebuilt identically
  • Version-controlled image definitions
  • Automated deployment pipeline ready for CI/CD integration
  • Documentation that lives alongside your code
  • Audit trail of every change and deployment

The Bigger Picture: Infrastructure as Code Maturity

This Packer implementation is just the beginning.
Once you’ve automated image creation, you’re ready for the next level:

  • CI/CD integration with GitHub Actions or Azure DevOps
  • Automated testing of your images before deployment
  • Multi-environment image management
  • Security scanning integrated into your build pipeline
  • Cost optimization through automated resource cleanup

Ready to Transform Your Infrastructure?

Manual image management is a relic of the past. Every minute you spend clicking through configuration dialogs is time stolen from solving real problems and building innovative solutions.

In my next post, I’ll show you how to integrate this Packer workflow into a complete CI/CD pipeline, including automated testing, security scanning, and deployment orchestration. Because building the image is just the first step—deploying it reliably is where the real magic happens.

If you’re intrigued by the possibilities of automating your image management and want to take it even further, let’s talk! I can help you implement this solution in your environment, integrate it with CI/CD pipelines, and even build a custom GUI to make it a point-and-click experience for your team.


Questions? Feedback? Reach out directly. I’m always interested in hearing how other teams are tackling infrastructure automation challenges.