π Packer β Full End-to-End Tutorial¶
(Beginner β Startup β Enterprise)



π§ What Packer Actually Does¶
HashiCorp Packer builds machine images automatically.
Instead of:
- Manually creating VMs
- Installing software again and again
- Debugging βworks on my serverβ
You:
- Define image once
- Build it consistently
- Reuse it everywhere
π§± Where Packer Fits (Mental Model)¶
Packer bakes the server Terraform serves the server
1οΈβ£ Install Packer¶
Linux¶
macOS¶
Verify¶
2οΈβ£ Core Packer Concepts (Non-Negotiable)¶
| Term | Meaning |
|---|---|
| Builder | Where image is built (AWS, Azure, Docker) |
| Provisioner | What is installed |
| Source | Image definition |
| Build | Execution logic |
| Template | .pkr.hcl file |
3οΈβ£ Golden Image Strategy (Enterprise Standard)¶


What is a Golden Image?¶
A Golden Image is a secure, hardened, versioned base image approved by platform/security teams.
β No SSH fixes β No manual installs β Immutable servers β Fast scaling β Audit-friendly
π§± Golden Image Layers (IMPORTANT)¶
Layer 1 β OS Base (Rarely changes)¶
- Ubuntu / RHEL
- OS updates
- CIS hardening
- SSH hardening
- Logging + monitoring agents
Layer 2 β Runtime (Monthly)¶
- Docker
- Nginx
- Node / Java / Go
- Cloud agents
Layer 3 β App (Optional)¶
- Legacy apps only
- No secrets
- Not used in Kubernetes-heavy setups
π·οΈ Naming Convention (Mandatory)¶
4οΈβ£ Real Startup-Grade Repo Structure¶
This is exactly how real startups structure it π
packer-images/
βββ README.md
βββ Makefile
βββ .github/
β βββ workflows/
β βββ packer.yml
βββ images/
β βββ ubuntu-base/
β β βββ main.pkr.hcl
β β βββ variables.pkr.hcl
β β βββ scripts/
β β βββ os-update.sh
β β βββ hardening.sh
β β βββ cleanup.sh
β βββ ubuntu-runtime/
β βββ main.pkr.hcl
β βββ variables.pkr.hcl
β βββ scripts/
β βββ docker.sh
β βββ nginx.sh
β βββ monitoring.sh
βββ modules/
β βββ aws.pkr.hcl
βββ scripts/
βββ common.sh
5οΈβ£ Build Golden Base Image (AWS)¶
Prerequisite¶
variables.pkr.hcl¶
main.pkr.hcl (Base Image)¶
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = "~> 1.3"
}
}
}
source "amazon-ebs" "ubuntu-base" {
region = var.region
instance_type = var.instance_type
ssh_username = "ubuntu"
ami_name = "golden-ubuntu-base-{{timestamp}}"
source_ami_filter {
filters = {
name = "ubuntu/images/*ubuntu-jammy-22.04-amd64-server-*"
virtualization-type = "hvm"
}
owners = ["099720109477"]
most_recent = true
}
}
scripts/os-update.sh¶
scripts/hardening.sh¶
#!/bin/bash
sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl restart ssh
scripts/cleanup.sh¶
Build Block¶
build {
sources = ["source.amazon-ebs.ubuntu-base"]
provisioner "shell" {
scripts = [
"scripts/os-update.sh",
"scripts/hardening.sh",
"scripts/cleanup.sh"
]
}
}
Run¶
β Golden OS Image Ready
6οΈβ£ Runtime Image (Layered on Base)¶
Change source AMI¶
source "amazon-ebs" "ubuntu-runtime" {
ami_name = "golden-ubuntu-runtime-{{timestamp}}"
source_ami = "ami-BASE_IMAGE_ID"
}
scripts/docker.sh¶
scripts/nginx.sh¶
Build Runtime Image¶
β Docker + Nginx baked in
7οΈβ£ CI/CD β GitHub Actions¶


.github/workflows/packer.yml¶
name: Build Golden Image
on:
push:
branches: [main]
jobs:
packer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-packer@v3
- run: packer init images/ubuntu-runtime
- run: packer validate images/ubuntu-runtime
- run: packer build images/ubuntu-runtime
8οΈβ£ Terraform Integration (Real Production)¶
data "aws_ami" "golden" {
most_recent = true
owners = ["self"]
filter {
name = "name"
values = ["golden-ubuntu-runtime-*"]
}
}
resource "aws_instance" "app" {
ami = data.aws_ami.golden.id
instance_type = "t2.micro"
}
9οΈβ£ Security & Best Practices¶
β No secrets in image β IAM roles only β Disable SSH in prod β Scan images β Immutable deployments
π₯ Real Startup Workflow¶
No SSH No hotfix No panic
π§ One-Line Summary¶
Packer creates the server you trust. Terraform runs the server you trust.