Building Golden Machine Images with Packer (and AI)
Immutable infrastructure starts with a solid golden image. Here's how to build reproducible machine images with Packer, and where AI accelerates the work.
- #iac
- #packer
- #immutable-infrastructure
- #images
- #automation
- #ai
There are two ways to get a server into the state you want. You can boot a generic image and configure it at launch — slower, and every boot is a chance for something to differ. Or you can bake everything into the image ahead of time, so launching is just “turn it on.” The second approach is immutable infrastructure, and Packer is how you build the images.
I’ve moved several fleets from configure-at-boot to baked golden images, and the payoff is consistency: every instance is byte-identical, boots in seconds, and there’s no configuration step to fail at 3am. Here’s how I build images that stay maintainable, with AI handling the tedious parts.
Why golden images beat configure-at-boot
A golden image is a pre-built machine image with the OS, packages, agents, and base config already baked in. The case for it:
- Speed. Launching is near-instant — no package downloads, no provisioning at boot.
- Consistency. Every instance from the image is identical. No “this one got a different package version because the mirror changed.”
- Reliability. Configuration happens once, at build time, where a failure stops a build instead of a production launch.
- Auditability. The image is a fixed, versioned artifact you can scan, sign, and promote.
The tradeoff is that changes mean rebuilding and redeploying the image rather than patching in place. That’s a feature — it’s what makes the fleet immutable — but it requires a build pipeline.
Anatomy of a Packer build
A Packer template has two halves: builders (what platform and base image) and provisioners (what to do to it). Here’s a minimal HCL template:
source "amazon-ebs" "base" {
ami_name = "app-base-{{timestamp}}"
instance_type = "t3.medium"
region = "us-east-1"
source_ami_filter {
filters = { name = "ubuntu/images/*22.04-amd64-server-*" }
owners = ["099720109477"]
most_recent = true
}
ssh_username = "ubuntu"
}
build {
sources = ["source.amazon-ebs.base"]
provisioner "ansible" {
playbook_file = "./base.yml"
}
}
packer build . boots a temporary instance, runs your Ansible playbook against it, snapshots the result into an AMI, and tears down the instance. The output is a versioned image ID you promote like any artifact — which ties straight into multi-environment promotion.
Provision with your existing config management
Notice the provisioner above is Ansible, not a pile of inline shell. That’s deliberate. Reuse your existing roles to build the image rather than maintaining a separate set of shell scripts that drift from how you configure everything else. One source of truth for “how a host should look,” used both for image builds and any runtime config.
This is where AI helps most: converting ad-hoc setup scripts into clean provisioner steps. Paste a messy bootstrap script and ask “convert this into an Ansible playbook suitable for a Packer build, idempotent where it matters.” You get a maintainable provisioner instead of accreting more shell. I keep image-build prompts tuned for this conversion.
Keep base images minimal and layered
A 12GB image full of every tool anyone might want is slow to build, slow to launch, and a fat attack surface. Keep the base minimal: OS hardening, the runtime, monitoring/log agents, and nothing else.
Layer on top of it. Build a thin base image (hardening + agents), then build app images from the base. The base rebuilds rarely; app images rebuild often and inherit the hardened foundation. This keeps app builds fast and means a hardening fix propagates by rebuilding the base once.
Bake security in at build time
Building images gives you a natural choke point to enforce security, and you should use it:
- Run a hardening role (CIS-style) as a provisioner so every image is hardened by construction.
- Scan the image before publishing. A
trivy imageor equivalent step in the build that fails on critical CVEs. Catching a vulnerable package at build time beats discovering it in prod. - Don’t bake secrets in. This is the cardinal sin — a credential baked into an image is in every instance and every snapshot. Secrets come from a store at runtime, never from the image.
provisioner "shell" {
inline = ["trivy rootfs --severity CRITICAL --exit-code 1 /"]
}
Version, promote, and expire images
An image is an artifact, so treat it like one:
- Version every build (timestamp or semver in the name) so you always know exactly what’s running.
- Promote the same image through environments — the AMI you validated in staging is the one that reaches prod. No rebuild between environments.
- Expire old images with a retention policy. Stale images accumulate cost and tempt someone into launching a months-old, unpatched build.
Where AI fits in image building
To be precise about the division of labor:
- Script-to-provisioner conversion — turning bootstrap shell into clean Ansible/provisioner steps. Best ROI.
- Generating Packer templates from a description of the platform and base OS.
- Reviewing for the secret-baking trap — “does this build bake any credential into the image?”
- Explaining scan findings — paste a Trivy report, get the fix priority.
What AI won’t do is run your build or vouch for the result. Every image must pass its scan and boot-test before it earns promotion. Treat AI as the engineer who writes the provisioner draft; the pipeline is what certifies the image.
Getting started
You don’t need the full pipeline on day one:
- Write one Packer template that bakes your current config (AI converts the script).
- Add a scan step that fails on critical CVEs.
- Version and promote the same image across environments.
- Split into base + app layers once builds get slow.
- Add a retention policy before old images pile up.
Golden images turn “configure a server” into “launch an artifact.” That shift — from imperative setup to immutable artifacts — is what makes a fleet predictable. Keep your conversion prompts in a prompt library and let the build pipeline be the thing that certifies every image.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.