Skip to content

πŸš€ Packer β€” Full End-to-End Tutorial

(Beginner β†’ Startup β†’ Enterprise)

Image

Image

Image


🧠 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  β†’  Golden Image  β†’  Terraform  β†’  Servers
Bake        Approve          Serve

Packer bakes the server Terraform serves the server


1️⃣ Install Packer

Linux

sudo apt update
sudo apt install packer -y

macOS

brew install packer

Verify

packer version

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)

Image

Image

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)

golden-ubuntu-22.04-runtime-v2025.01.15

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

aws configure

variables.pkr.hcl

variable "region" {
  default = "ap-south-1"
}

variable "instance_type" {
  default = "t2.micro"
}

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

#!/bin/bash
set -e
sudo apt update && sudo apt upgrade -y

scripts/hardening.sh

#!/bin/bash
sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl restart ssh

scripts/cleanup.sh

#!/bin/bash
sudo apt autoremove -y
sudo apt clean

Build Block

build {
  sources = ["source.amazon-ebs.ubuntu-base"]

  provisioner "shell" {
    scripts = [
      "scripts/os-update.sh",
      "scripts/hardening.sh",
      "scripts/cleanup.sh"
    ]
  }
}

Run

packer init .
packer validate .
packer build .

βœ… 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

sudo apt install -y docker.io
sudo systemctl enable docker

scripts/nginx.sh

sudo apt install -y nginx
sudo systemctl enable nginx

Build Runtime Image

packer build .

βœ… Docker + Nginx baked in


7️⃣ CI/CD β€” GitHub Actions

Image

Image

.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

PR β†’ Packer Build β†’ Scan β†’ Approve β†’ Terraform Apply

No SSH No hotfix No panic


🧠 One-Line Summary

Packer creates the server you trust. Terraform runs the server you trust.