hashicorp/packer
Packer is a tool for creating identical machine images for multiple platforms from a single source configuration.
Healthy across the board
worst of 4 axesnon-standard license (Other)
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓12 active contributors
- ✓Distributed ownership (top contributor 40% of recent commits)
Show 4 more →Show less
- ✓Other licensed
- ✓CI configured
- ✓Tests present
- ⚠Non-standard license (Other) — review terms
What would change the summary?
- →Use as dependency Concerns → Mixed if: clarify license terms
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/hashicorp/packer)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/hashicorp/packer on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: hashicorp/packer
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/hashicorp/packer shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit today
- 12 active contributors
- Distributed ownership (top contributor 40% of recent commits)
- Other licensed
- CI configured
- Tests present
- ⚠ Non-standard license (Other) — review terms
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live hashicorp/packer
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/hashicorp/packer.
What it runs against: a local clone of hashicorp/packer — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in hashicorp/packer | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of hashicorp/packer. If you don't
# have one yet, run these first:
#
# git clone https://github.com/hashicorp/packer.git
# cd packer
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of hashicorp/packer and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "hashicorp/packer(\\.git)?\\b" \\
&& ok "origin remote is hashicorp/packer" \\
|| miss "origin remote is not hashicorp/packer (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "command/build.go" \\
&& ok "command/build.go" \\
|| miss "missing critical file: command/build.go"
test -f "command/execute.go" \\
&& ok "command/execute.go" \\
|| miss "missing critical file: command/execute.go"
test -f "builder/file/builder.go" \\
&& ok "builder/file/builder.go" \\
|| miss "missing critical file: builder/file/builder.go"
test -f "builder/null/builder.go" \\
&& ok "builder/null/builder.go" \\
|| miss "missing critical file: builder/null/builder.go"
test -f "command/cli.go" \\
&& ok "command/cli.go" \\
|| miss "missing critical file: command/cli.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/hashicorp/packer"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Packer is HashiCorp's infrastructure-as-code tool that generates identical machine images (AMIs, VHDs, OVAs, etc.) for multiple cloud platforms and virtualization providers from a single HCL configuration file. It parallelizes image builds across AWS, Azure, Google Cloud, VMware, and 50+ other platforms via a plugin architecture, enabling teams to define golden images once and deploy them anywhere. Monorepo: core Packer CLI in root with builder/ subdirectories per provider (builder/file/, builder/amazon/, etc.), acctest/ for acceptance tests, .release/ for CI artifacts, .github/workflows/ for build pipelines. Plugin SDK in separate dependency (github.com/hashicorp/packer-plugin-sdk). Configuration parsing uses HCL2 (github.com/hashicorp/hcl/v2) and Go's plugin system for dynamic provider loading.
👥Who it's for
DevOps engineers, infrastructure teams, and platform engineers who need to build and maintain consistent machine images across heterogeneous cloud environments (AWS, Azure, GCP, etc.) without writing separate build logic for each platform. Also used by organizations adopting Infrastructure-as-Code practices with Terraform/HCP.
🌱Maturity & risk
Production-ready and actively maintained by HashiCorp. The codebase is substantial (~1.7M Go LOC), has comprehensive GitHub Actions CI/CD workflows (acceptance-test.yml, go-test.yml, go-validate.yml, nightly-release.yml), official documentation on developer.hashicorp.com, and maintains strict release processes (.release/ directory with artifact/metadata configs). Project uses BUSL-1.1 license indicating commercial backing.
Standard open source risks apply.
Active areas of work
Active development with nightly releases, dependabot dependency management, backport automation, Jira integration, and stale-issue auto-closure. Acceptance test suite runs on every commit. Documentation has migrated to hashicorp/web-unified-docs (per CONTRIBUTING.md), indicating ongoing docs refactoring.
🚀Get running
git clone https://github.com/hashicorp/packer.git
cd packer
make dev # Builds packer binary for local dev
packer version # Verify installation
packer init # Initialize a Packer config
packer build example.pkr.hcl # Example build
Requires Go (see .go-version), and cloud credentials for your target platform.
Daily commands:
make dev # Build Packer binary to ./bin/
make test # Run Go unit tests
make testacc # Run acceptance tests (requires cloud creds)
make fmt # Format code with gofmt
make lint # Run golangci-lint (config: .golangci.yml)
./bin/packer build -debug examples/ # Run a local build with debug output
🗺️Map of the codebase
command/build.go— Core build command orchestration logic; all image builds flow through this entry pointcommand/execute.go— Main CLI execution dispatcher that routes commands and initializes the build contextbuilder/file/builder.go— Reference builder implementation; understand this to extend Packer with new buildersbuilder/null/builder.go— Null builder demonstrates SSH/WinRM provisioning patterns used across all platform builderscommand/cli.go— CLI flag definitions and configuration parsing; defines how users interact with PackerMakefile— Build system and local development targets; required to understand project build process.go-version— Specifies minimum Go version; critical for dependency compatibility and local setup
🧩Components & responsibilities
- CLI & Commands (command/) (Go CLI framework, HCL2 parser) — Parse user input, load HCL configs, dispatch build/fix/console operations, manage lifecycle
- Failure mode: Invalid config syntax, missing files, flag parsing errors halt before build
- Builder Interface (Go interfaces, plugin protocol) — Abstract interface implemented by platform builders; defines Prepare/Run/Cancel lifecycle
- Failure mode: Builder crash/panic propagates to Packer; entire build fails without rollback
- SSH/WinRM Communicators (golang.org/x/crypto/ssh, WinRM client) — Establish and manage remote connections for provisioning; handle file upload, command execution
- Failure mode: Connection timeout, authentication failure, or remote command error halts build with partial cleanup
- Artifact Management (Go interfaces, cloud provider APIs) — Represent built image state; expose metadata, handle cleanup/export of build outputs
- Failure mode: Artifact export/cleanup failure may leave orphaned resources (e.g., untagged AMIs)
- HCL2 Configuration (go-cty, HCL2 parser) — Parse and validate .pkr.hcl files; merge multiple config files; evaluate dynamic expressions
- Failure mode: Type errors, unknown variables, or syntax errors
🛠️How to make changes
Add a new Builder
- Create new builder directory structure at builder/{platform}/ (
builder/file/builder.go) - Define config struct and implement unmarshalling in config.go, then run go generate to create config_hcl2spec.go (
builder/file/config.go) - Implement Builder interface (Prepare, Run, Cancel) in builder.go with platform-specific provisioning logic (
builder/file/builder.go) - Implement Artifact interface for cleanup and state management in artifact.go (
builder/file/artifact.go) - Add unit and acceptance tests following existing patterns in builder_test.go and artifact_test.go (
builder/file/builder_test.go) - Register builder plugin in version/version.go with proper version constraints (
builder/file/version/version.go)
Add a new CLI Command
- Create new command struct implementing Command interface in command/{name}.go (
command/build.go) - Define command flags and implement Help() and Run() methods following existing patterns (
command/cli.go) - Register command in dispatcher by adding case in execute.go's main switch statement (
command/execute.go) - Add corresponding test file {name}_test.go with unit tests (
command/build_test.go)
Configure Remote Provisioning (SSH/WinRM)
- Reference null builder's SSH setup pattern in ssh.go for connection configuration (
builder/null/ssh.go) - Define communicator config in your builder's config.go struct (follow null builder pattern) (
builder/null/config.go) - Use ssh.go connection primitives in your builder's Run() method for remote execution (
builder/null/builder.go) - Add integration tests using acctest harness to validate remote connectivity (
acctest/testing.go)
🔧Why these technologies
- Go — Cross-platform native compilation, single binary distribution, excellent concurrency for parallel image builds
- HCL2 (go-cty) — Domain-specific syntax familiar to Terraform users, dynamic expressions, plugin-agnostic configuration language
- Plugin architecture (gRPC-based) — Decouples platform-specific builders from core, allows community contributions without main repo changes
- SSH/WinRM communicators — Enables provisioning on remote instances across cloud providers without platform-specific APIs
⚖️Trade-offs already made
-
External builders as plugins rather than monolithic codebase
- Why: Reduces maintenance burden and allows independent versioning of builders
- Consequence: Requires plugin protocol overhead; builders cannot directly access Packer internals
-
HCL2 configuration instead of JSON/YAML
- Why: Enables dynamic expressions and computed values; familiar to Terraform users
- Consequence: Steeper learning curve for non-Terraform users; requires HCL parser dependencies
-
Single-pass build (no incremental layer caching)
- Why: Simplifies semantics and ensures reproducibility; every build starts fresh
- Consequence: Slower builds on repeated configurations; no intermediate image artifacts
🚫Non-goals (don't propose these)
- Real-time infrastructure provisioning (static image building only, not infrastructure-as-code orchestration)
- Multi-tenant isolation (designed for individual/team use, not SaaS platform)
- Container image building (focused on VM/machine images, not OCI/Docker; though Docker images are supported as targets)
- Configuration secrets management (users must provide secrets; Packer does not encrypt/rotate)
🪤Traps & gotchas
- Builders are loaded as external plugins, not compiled in—missing plugin binary = confusing 'builder not found' error (check plugin cache in ~/.packer.d/plugins/). 2) HCL2 requires
required_versionandrequired_pluginsblocks in modern configs; old HCL will fail silently. 3) Acceptance tests require real cloud credentials (AWS_PROFILE, GOOGLE_APPLICATION_CREDENTIALS, etc.)—set these before running make testacc. 4) Windows WinRM provisioning (masterzen/winrm) requires firewall/port 5985 open on target; SSH timeouts are a GitHub issue template, suggesting common pain point. 5) Plugin SDK version mismatch between packer core and plugins causes runtime errors—always match versions in go.mod.
🏗️Architecture
💡Concepts to learn
- Plugin Architecture (Go plugins + RPC) — Packer dynamically discovers and loads builders/provisioners as external binaries via HashiCorp's plugin system—essential for understanding why builder errors occur and how to extend Packer
- HCL2 (HashiCorp Configuration Language v2) — Packer configs are written in HCL2, not JSON or YAML—understanding blocks, expressions, and validation is critical for writing .pkr.hcl files and debugging config errors
- Artifact Interface — Each builder produces an Artifact (AMI ID, VHD path, etc.)—this abstraction allows Packer to handle heterogeneous outputs uniformly and pass them to post-processors
- Parallel Build Execution — Packer's core strength is building the same image across multiple platforms simultaneously—understanding build graph dependencies and parallelization limits is key to optimizing image pipelines
- Provisioner vs. Builder — Builders create the base instance (e.g., EC2 AMI), while provisioners run commands on it (shell, Chef, Ansible); conflating these is a common mistake
- Post-Processor Chaining — Artifacts can flow through multiple post-processors (e.g., AWS → Vagrant box → artifact registry) in sequence—this enables complex image distribution workflows
- Data Sources in Packer — HCL2 data sources (e.g., ami-filter in acctest/plugin/test-fixtures/basic-amazon-ami-datasource.pkr.hcl) let configs query external info dynamically—needed for referencing existing resources
🔗Related repos
hashicorp/terraform— Packer image outputs (AMI IDs, etc.) are typically consumed by Terraform for infrastructure provisioning; users need bothhashicorp/vagrant— Packer can generate Vagrant boxes (.box files) from built images; explicitly mentioned in README as a Packer use casehashicorp/packer-plugin-sdk— Separate repo defining the plugin interface and helper libraries—required dependency for writing custom Packer pluginshashicorp/web-unified-docs— Packer docs have migrated here (per CONTRIBUTING.md); contribute Packer documentation changes there, not in this repoimage-builder/image-builder— Kubernetes Image Builder uses Packer to build node images; demonstrates Packer's use in large-scale infrastructure projects
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for SSH/WinRM timeout scenarios
The repo has a dedicated GitHub issue template (.github/ISSUE_TEMPLATE/ssh_or_winrm_times_out.md) indicating this is a frequent pain point for users. However, there are no visible acceptance tests in acctest/ that specifically cover SSH/WinRM connection timeout handling, retry logic, or graceful failure modes. Adding comprehensive tests would reduce regressions and give users confidence in timeout behavior.
- [ ] Create acctest/ssh_winrm_timeout_test.go with test fixtures for various timeout scenarios
- [ ] Add test cases for: connection refused, read timeout, write timeout, and graceful shutdown
- [ ] Reference builder/null/ssh.go implementation to understand current timeout handling
- [ ] Integrate tests into .github/workflows/acceptance-test.yml if not already covered
- [ ] Document expected timeout behavior in tests for future maintainers
Add unit tests for builder/file package
The builder/file package has test files (builder/file/config_test.go, builder/file/artifact_test.go, builder/file/builder_test.go) but coverage appears incomplete. The artifact.go file lacks corresponding comprehensive tests for edge cases like file permissions, special characters in paths, and symlink handling. This is a low-risk, high-impact area since file operations are critical to image building.
- [ ] Review existing tests in builder/file/*_test.go to identify gaps
- [ ] Add tests to builder/file/artifact_test.go for: empty files, large files, permission preservation, special characters
- [ ] Add tests to builder/file/config_test.go for: invalid paths, relative paths, environment variable expansion
- [ ] Verify test coverage reaches >80% using go test -cover ./builder/file/...
- [ ] Run tests locally: make test or go test ./builder/file/...
Create validation workflow for HCL2 test fixtures
The repo has test fixtures in acctest/plugin/test-fixtures/*.pkr.hcl and builder/file/test-fixtures/ but no CI workflow validates that these HCL files are syntactically correct or can be parsed by the current codebase. Adding a validation step would catch broken fixtures early and ensure documentation stays accurate.
- [ ] Create .github/workflows/validate-hcl-fixtures.yml workflow
- [ ] Use packer validate command (or programmatic HCL2 parsing) to check all .pkr.hcl files in acctest/ and builder/*/test-fixtures/
- [ ] Ensure workflow runs on pull requests and reports failures clearly
- [ ] Reference .github/workflows/go-validate.yml as a template for structure
- [ ] Document the validation process in .github/CONTRIBUTING.md
🌿Good first issues
- Add missing unit tests for builder/file/ or other bundled builders—look for *_test.go gaps and add happy-path + error cases following Go testing conventions
- Document a commonly-missed HCL feature or plugin in web-unified-docs fork, then open PR; CONTRIBUTING.md explicitly mentions docs are now external
- Create a minimal acceptance test fixture in acctest/plugin/test-fixtures/ for a supported-but-untested provider (e.g., docker, null) following the pattern of basic-amazon-ebs.pkr.hcl
⭐Top contributors
Click to expand
Top contributors
- @tanmay-hc — 40 commits
- @kp2099 — 19 commits
- @anurag5sh — 12 commits
- @hariom-hashicorp — 8 commits
- @dependabot[bot] — 8 commits
📝Recent commits
Click to expand
Recent commits
342fc1c— Merge pull request #13625 from hashicorp/cut-release-1.15.3 (tanmay-hc)08fe313— version: cut release v1.15.3 (tanmay-hc)f411630— Merge pull request #13624 from hashicorp/bucket-fix (tanmay-hc)072dfde— Skips bucket update when metadata matches current state (tanmay-hc)48f5e6b— fix(deps): update github.com/Azure/go-ntlmssp to v0.1.1 (#13622) (hariom-hashicorp)68a5acd— build(deps): bump github.com/Azure/go-ntlmssp (#13620) (dependabot[bot])9ca74f7— Bump version to 1.15.2 and update changelog for release (#13618) (hariom-hashicorp)6a8612c— Update error message in TestSourceNotExisting for clarity (#13616) (hariom-hashicorp)627c9f1— Merge pull request #13615 from hashicorp/go-fix (tanmay-hc)c45722b— Update Go version and refresh dependencies (tanmay-hc)
🔒Security observations
The HashiCorp Packer codebase demonstrates reasonable security practices with dependency management tooling and CI/CD workflows in place. However, several medium-severity issues require attention: (1) dependency versions need auditing for known CVEs, particularly go-getter, go-git, and github API client; (2) Docker image hardening is incomplete with unpinned base images and missing binary verification; (3) missing go.sum verification context; (4) absence of a formal security disclosure policy. The
- Medium · Outdated and Potentially Vulnerable Dependencies —
go.mod (Dependencies/Package file). Several dependencies have outdated versions with known vulnerabilities. Notably: github.com/google/go-github/v33 (from 2021), github.com/go-git/go-git/v5 (v5.18.0 is older), and github.com/masterzen/winrm with a very recent version that may not be stable. The dependency on go-getter/v2 v2.2.2 should be verified for path traversal vulnerabilities. Fix: Audit and update all dependencies to their latest stable versions. Run 'go mod tidy' and review security advisories for each dependency using 'go list -json -m all | nancy' or similar tools. Particularly review github.com/hashicorp/go-getter for CVE-2024-6257 and similar. - Medium · Missing go.sum Integrity Verification —
Repository root (go.sum should exist). The go.sum file is not provided in the codebase context, which is critical for Go module integrity verification. This could allow man-in-the-middle attacks or module substitution attacks during build processes. Fix: Ensure go.sum is committed to version control and regularly verified. Use 'go mod verify' in CI/CD pipelines to validate module checksums before builds. - Medium · Incomplete Dockerfile Security Hardening —
Dockerfile (dev target). The Dockerfile uses 'alpine:latest' without specifying a pinned version tag, creating build reproducibility and security update issues. The dev image copies binaries directly without verification of their integrity. Missing security scanning in the build process. Fix: Pin Alpine Linux to a specific version (e.g., 'alpine:3.19'). Add COPY integrity checks using checksums. Implement image scanning using tools like Trivy or Snyk in CI/CD before release builds. Remove unnecessary packages from runtime images. - Low · Incomplete Dockerfile (Truncated Content) —
Dockerfile. The Dockerfile appears to be incomplete (ends with 'Lig' comment), suggesting the provided snippet may not reflect the actual production Dockerfile. This could hide security issues in the complete implementation. Fix: Verify the complete Dockerfile content. Ensure all targets (release-light, etc.) follow security best practices including: non-root user execution, minimal base images, and no embedded secrets. - Low · License Header Present (BUSL-1.1) —
Dockerfile header, LICENSE file. The codebase uses BUSL-1.1 (Business Source License) which has specific commercial restrictions. This is informational but should be clearly communicated to users and contributors. Fix: Ensure clear communication of license terms in documentation. Verify proper license headers in all source files. Review BUSL-1.1 restrictions for your use case. - Low · No Security Policy File Detected —
Repository root (missing SECURITY.md). While security templates exist in .github/ISSUE_TEMPLATE (ssh_or_winrm_times_out.md), there is no SECURITY.md file for responsible disclosure of vulnerabilities. Fix: Create a SECURITY.md file documenting the vulnerability disclosure process, supported versions, and security update timelines. GitHub can use this for security advisories. - Low · Dependabot Configuration Present but Needs Verification —
.github/dependabot.yml. A .github/dependabot.yml file exists which is good for dependency management, but its specific configuration cannot be assessed from the provided content. Ensure it's properly configured for Go modules. Fix: Verify dependabot.yml configures automated security updates with appropriate review requirements. Ensure Go module updates are prioritized. Consider implementing automated merging for patch/minor version updates after testing.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.