How to Create a Terraform Archive File for Deployment: A Complete Guide
The most effective method for creating a terraform archive file is using terraform plan -out=plan.zip, which internally invokes the planfile.Create function to bundle the plan, state files, configuration snapshot, and lock file into a single zip archive.
A terraform archive file serves as the deployment artifact in Terraform's remote execution workflow, encapsulating everything needed to apply infrastructure changes without access to the original configuration source. This article examines the implementation in the hashicorp/terraform repository to explain how these archives are structured, generated, and used in production deployment pipelines.
What Is a Terraform Archive File?
A terraform archive file is a zip archive that contains the complete context required to execute a plan remotely. According to the source code in internal/plans/planfile/writer.go, the archive bundles five critical components:
- Serialized plan (
tfplan): The binary plan output containing the proposed resource changes - Current state (
tfstate): The latest Terraform state file after refresh operations - Previous state (
tfstate-prev): The state file from before the last apply operation - Configuration snapshot: A complete copy of the
.terraformmodule tree and configuration files stored under a virtualtfconfig/directory - Dependency lock file (
dependency-locks.hcl): The.terraform.lock.hclcontent when present, ensuring consistent provider versions
How Terraform Creates Archive Files Internally
The archive creation process centers on the planfile.Create function located in internal/plans/planfile/writer.go. This function is invoked by the CLI when executing terraform plan -out=<filename> and by remote backends when preparing deployment artifacts.
The Archive Creation Process in writer.go
The planfile.Create function executes a precise sequence of operations to construct the zip archive:
- Open output file (line 55): Uses
os.Createto open or truncate the target archive file - Initialize zip writer (line 61): Wraps the file handle with
zip.NewWriterto begin zip entry construction - Write plan binary (lines 66-74): Serializes the
plans.Planobject into atfplanentry usingDeflatecompression - Embed current state (lines 80-92): Calls
statefile.Writeto store the refreshed state astfstate - Embed previous state (lines 96-108): Stores the prior run state as
tfstate-prevusing the same method - Snapshot configuration (lines 112-119): Walks the configuration directory and stores each file under the virtual
tfconfig/path - Include lock file (lines 120-138): If
DependencyLocksis provided, writes the content asdependency-locks.hcl - Finalize archive (line 141): Closes the zip writer to flush all entries and complete the archive
Backend Integration
The archive creation is triggered from backend implementations after a successful plan operation. In internal/backend/local/backend_plan.go at line 187, the local backend invokes planfile.Create to persist the plan and its associated context to disk:
// From internal/backend/local/backend_plan.go
if err := planfile.Create(planOutPath, planfile.CreateArgs{
ConfigSnapshot: configSnapshot,
PreviousRunStateFile: previousStateFile,
StateFile: stateFile,
Plan: plan,
DependencyLocks: dependencyLocks,
}); err != nil {
// Handle error
}
Creating a Terraform Archive File: CLI Method
For standard deployment workflows, use the Terraform CLI to generate the archive automatically. This method ensures all components are correctly serialized and compressed according to the internal specification.
# Create a plan and save it as a zip archive
terraform plan -out=deployment-plan.zip
# Apply the archived plan on a remote executor or different machine
terraform apply deployment-plan.zip
When you specify the -out flag, Terraform executes the full plan workflow, then calls planfile.Create to bundle the resulting plan with the current state, configuration snapshot, and lock file into the specified zip archive.
Creating a Terraform Archive File Programmatically
For custom tooling or CI/CD pipelines that need to generate archives without invoking the CLI directly, use the internal planfile package. This approach requires importing the Terraform internal packages and constructing the CreateArgs struct with properly initialized objects.
package main
import (
"log"
"github.com/hashicorp/terraform/internal/configs/configload"
"github.com/hashicorp/terraform/internal/depsfile"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/plans/planfile"
"github.com/hashicorp/terraform/internal/states/statefile"
)
func main() {
// These objects would be populated from your Terraform workflow:
var cfgSnap *configload.Snapshot // Configuration snapshot
var prevState *statefile.File // Previous run state
var curState *statefile.File // Current refreshed state
var tfPlan *plans.Plan // The computed plan
var locks *depsfile.Locks // Dependency locks (optional)
args := planfile.CreateArgs{
ConfigSnapshot: cfgSnap,
PreviousRunStateFile: prevState,
StateFile: curState,
Plan: tfPlan,
DependencyLocks: locks,
}
// Create the archive at the specified path
if err := planfile.Create("deployment-plan.zip", args); err != nil {
log.Fatalf("failed to create terraform archive file: %v", err)
}
}
Important considerations for programmatic use:
- Import paths use
github.com/hashicorp/terraform/internal/...which are internal packages subject to change between releases - The
ConfigSnapshotmust contain the complete module tree and configuration files - State files must be properly formatted
*statefile.Fileobjects, not raw JSON - Dependency locks ensure provider version consistency across execution environments
Key Source Files for Terraform Archive Creation
Understanding the implementation requires examining these specific files in the hashicorp/terraform repository:
| File | Purpose |
|---|---|
internal/plans/planfile/writer.go |
Core implementation of planfile.Create that constructs the zip archive with all components |
internal/backend/local/backend_plan.go |
Local backend that invokes planfile.Create at line 187 after plan execution |
internal/plans/planfile/reader.go |
Counterpart that reads and validates the archive on the remote execution side |
internal/terraform/context_test.go |
Test suite validating archive creation and extraction workflows |
internal/command/command_test.go |
Integration tests ensuring the CLI properly generates archive files |
Summary
- A terraform archive file is a zip bundle containing the plan binary, current and previous state files, configuration snapshot, and dependency locks required for remote execution.
- The most effective creation method is the CLI command
terraform plan -out=plan.zip, which internally callsplanfile.Createininternal/plans/planfile/writer.go. - For programmatic generation, import the internal
planfilepackage and populateCreateArgswith configuration snapshots, state files, and plan objects. - The archive format uses standard zip compression with specific entry names (
tfplan,tfstate,tfconfig/, etc.) that the reader implementation expects ininternal/plans/planfile/reader.go.
Frequently Asked Questions
What exactly is inside a terraform archive file?
A terraform archive file contains five essential components: the serialized plan binary (tfplan), the current state file (tfstate), the previous state file (tfstate-prev), a complete snapshot of your configuration stored under tfconfig/, and optionally the dependency lock file (dependency-locks.hcl). These components are bundled by the planfile.Create function in internal/plans/planfile/writer.go to ensure the remote executor has everything needed to apply the plan without access to your source repository.
Can I create a terraform archive file without using the CLI?
Yes, you can create a terraform archive file programmatically by importing the internal github.com/hashicorp/terraform/internal/plans/planfile package and calling planfile.Create with a populated CreateArgs struct. This approach requires constructing configuration snapshots, state file objects, and plan structures manually, which is typically only done when building custom CI/CD tooling. Note that internal packages are subject to breaking changes between Terraform releases.
How does Terraform Cloud use the archive file?
When you run terraform plan -out=plan.zip and configure a remote backend like Terraform Cloud, the CLI automatically uploads the archive file to the remote executor. The server-side implementation uses internal/plans/planfile/reader.go to extract the plan, state, and configuration snapshot from the zip entries. This allows the remote agent to apply the plan in a secure, isolated environment without requiring access to your local configuration files or state storage.
What compression method does Terraform use for archive files?
Terraform uses standard Deflate compression for the zip archive entries, specifically when writing the tfplan binary in internal/plans/planfile/writer.go (lines 66-74). The implementation uses Go's standard archive/zip package with zip.Deflate as the compression method. State files and configuration snapshots are also stored within the same zip container, though the specific compression settings may vary by entry type based on the writer implementation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →