• HashiCorp Developer

  • HashiCorp Cloud Platform
  • Terraform
  • Packer
  • Consul
  • Vault
  • Boundary
  • Nomad
  • Waypoint
  • Vagrant
Terraform
  • Install
  • Tutorials
    • About the Docs
    • Configuration Language
    • Terraform CLI
    • Terraform Cloud
    • Terraform Enterprise
    • CDK for Terraform
    • Provider Use
    • Plugin Development
    • Registry Publishing
    • Integration Program
  • Registry(opens in new tab)
  • Try Cloud(opens in new tab)
  • Sign up
Provision

Skip to main content
6 tutorials
  • Provision Infrastructure with Cloud-Init
  • Provision Infrastructure with Packer
  • Set Up Terraform Cloud Run Task for HCP Packer
  • Identify Compromised Images with Terraform Cloud
  • Enforce Image Compliance with Terraform Cloud
  • Standardize Machine Images Across Multiple Cloud Providers

  • Resources

  • Tutorial Library
  • Certifications
  • Community Forum
    (opens in new tab)
  • Support
    (opens in new tab)
  • GitHub
    (opens in new tab)
  • Terraform Registry
    (opens in new tab)
  1. Developer
  2. Terraform
  3. Tutorials
  4. Provision
  5. Provision Infrastructure with Packer

Provision Infrastructure with Packer

  • 5min

  • TerraformTerraform
  • PackerPacker

Packer is HashiCorp's open-source tool for creating machine images from source configuration. You can configure Packer images with an operating system and software for your specific use-case.

Terraform configuration for a compute instance can use a Packer image to provision your instance without manual configuration.

In this tutorial, you will create a Packer image with a user group, a new user with authorized SSH keys, and a Go web app. Then, you will deploy this image using Terraform. Finally, you will access the instance via SSH to deploy the Go web app.

Prerequisites

To follow along with this tutorial, you will need:

  • Packer 1.6.6 or later
  • Terraform
  • An AWS account
  • Local environment variables for your AWS account.

Clone the example repository here.

$ git clone -b packer https://github.com/hashicorp/learn-terraform-provisioning

Change into your cloned repo directory.

$ cd learn-terraform-provisioning

Create a local SSH key

For this tutorial, create a local SSH key to pair with the new terraform user you create on this instance.

Generate a new SSH key called tf-packer. The argument provided with the -f flag creates the key in the current directory and creates two files called tf-packer and tf-packer.pub. Change the placeholder email address to your email address.

$ ssh-keygen -t rsa -C "your_email@example.com" -f ./tf-packer

When prompted, press enter to leave the passphrase blank on this key.

If you are on a Windows machine, use Putty to generate SSH keys by following the instructions here.

Review the shell script

Packer's configuration will pass it a shell script to run when it builds the image. For more information on the other methods of delivering provisioning instructions to your image, visit the Packer provisioners documentation.

The script for this tutorial updates the default instance software, installs necessary apps, and creates a user with your SSH key created above.

Change directories into the scripts directory.

$ cd scripts

Open setup.sh in your file editor and review the provisioning instructions. This script installs the necessary dependencies, adds the terraform user to the sudo group, installs the previously created SSH key, and downloads the sample GoLang webapp. Use the comments in setup.sh to verify these steps before building the image.

#!/bin/bash
set -x

# Install necessary dependencies
sudo apt-get update -y
sudo DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
sudo apt-get update
sudo apt-get -y -qq install curl wget git vim apt-transport-https ca-certificates
sudo add-apt-repository ppa:longsleep/golang-backports -y
sudo apt-get -y -qq install golang-go

# Setup sudo to allow no-password sudo for "hashicorp" group and adding "terraform" user
sudo groupadd -r hashicorp
sudo useradd -m -s /bin/bash terraform
sudo usermod -a -G hashicorp terraform
sudo cp /etc/sudoers /etc/sudoers.orig
echo "terraform  ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/terraform

# Installing SSH key
sudo mkdir -p /home/terraform/.ssh
sudo chmod 700 /home/terraform/.ssh
sudo cp /tmp/tf-packer.pub /home/terraform/.ssh/authorized_keys
sudo chmod 600 /home/terraform/.ssh/authorized_keys
sudo chown -R terraform /home/terraform/.ssh
sudo usermod --shell /bin/bash terraform

# Create GOPATH for Terraform user & download the webapp from github

sudo -H -i -u terraform -- env bash << EOF
whoami
echo ~terraform

cd /home/terraform

export GOROOT=/usr/lib/go
export GOPATH=/home/terraform/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
go get -d github.com/hashicorp/learn-go-webapp-demo
EOF

Warning: Never pass unverified scripts into your Packer images.

Review the Packer image

Your Packer configuration defines the parameters of the image you want to build.

Change directories into images.

$ cd ../images

Open the image.pkr.hcl file in your file editor.

Review the variables block. This region must match the region where Terraform will build your AMI. If you customize it, you will need to customize the sample Terraform configuration to match (later on in the tutorial). The locals block creates a formatted timestamp to keep your AMI name unique.

variable "region" {
  type    = string
  default = "us-east-1"
}

locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }

The source block generates a template for your AMI. The source amazon-ebs declares this image will be created in AWS and uses Elastic Block Storage. This ami_name names the AMI learn-terraform-packer and searches for a base AMI in the source_ami_filter that matches your criteria of a t2.micro Ubuntu image with Elastic Block Storage (EBS) in your declared region.

source "amazon-ebs" "example" {
  ami_name      = "learn-terraform-packer-${local.timestamp}"
  instance_type = "t2.micro"
  region        = var.region
  source_ami_filter {
    filters = {
      name                = "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*"
      root-device-type    = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true
    owners      = ["099720109477"]
  }
  ssh_username = "ubuntu"
}

Finally, the build block builds out your instances with specific scripts or files. Your build is based on the previously declared source as the type of AMI.

Next, the provisioner blocks copy your key to the image and run your setup script.

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

  provisioner "file" {
    source      = "../tf-packer.pub"
    destination = "/tmp/tf-packer.pub"
  }
  provisioner "shell" {
    script = "../scripts/setup.sh"
  }
}

Build your Packer image

Run the Packer build command providing your image template file.

$ packer build image.pkr.hcl
amazon-ebs.example: output will be in this color.

==> amazon-ebs.example: Prevalidating any provided VPC information
==> amazon-ebs.example: Prevalidating AMI Name: learn-terraform-packer
    amazon-ebs.example: Found Image ID: ami-07f5c641c23596eb9
==> amazon-ebs.example: Creating temporary keypair: packer_601c660b-e33f-7875-ab03-ae9a42345198
==> amazon-ebs.example: Creating temporary security group for this instance: packer_601c660f-5a26-53d2-0321-7094c5044848
==> amazon-ebs.example: Authorizing access to port 22 from [0.0.0.0/0] in the temporary security groups...
==> amazon-ebs.example: Launching a source AWS instance...
## ...
==> amazon-ebs.example: Stopping the source instance...
    amazon-ebs.example: Stopping instance
==> amazon-ebs.example: Waiting for the instance to stop...
==> amazon-ebs.example: Creating AMI learn-terraform-packer from instance i-0054c6c995aacf330
    amazon-ebs.example: AMI: ami-0dbaca5d269497603
==> amazon-ebs.example: Waiting for AMI to become ready...
==> amazon-ebs.example: Skipping Enable AMI deprecation...
==> amazon-ebs.example: Terminating the source AWS instance...
==> amazon-ebs.example: Cleaning up any extra volumes...
==> amazon-ebs.example: No volumes to clean up, skipping
==> amazon-ebs.example: Deleting temporary security group...
==> amazon-ebs.example: Deleting temporary keypair...
Build 'amazon-ebs.example' finished after 5 minutes 42 seconds.

==> Wait completed after 5 minutes 42 seconds

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs.example: AMIs were created:
us-east-1: ami-0dbaca5d269497603

The final line of the output is the AMI ID you will pass into your Terraform configuration in the next step.

Deploy your Packer image with Terraform

The AMI is your artifact from the Packer run and is available in your AWS account in the EC2 Images section. You can visit the AWS Web Console to view this AMI ID again.

To use this AMI in your Terraform environment, navigate to the instances directory.

$ cd ../instances

Open the main.tf file and navigate to the aws_instance resource. Edit the ami attribute with the AMI ID you received from your Packer build.

##...
resource "aws_instance" "web" {
-  ami                         = "ami-YOUR-AMI-ID"
+  ami                         = "ami-0dbaca5d269497603"
  instance_type               = "t2.micro"
  subnet_id                   = aws_subnet.subnet_public.id
  vpc_security_group_ids      = [aws_security_group.sg_22_80.id]
  associate_public_ip_address = true

  tags = {
    Name = "Learn-Packer"
  }
}
##...

Save your configuration.

Create a new file called terraform.tfvars and add the Packer image's region as the variable definition. If you customized the region you gave to Packer you must change this region to match, or Terraform won't be able to access your image.

region = "us-east-1"

Save this file and then initialize and apply your configuration.

$ terraform init && terraform apply

Type yes when prompted to create your instance. Your final output is your instance IP address. In the next section, you will SSH into this instance with your local key.

Your instance in this tutorial already contains the preferred SSH key because it uses the AMI you previously packaged with Packer. Using a Packer-packaged AMI makes deploying mass instances faster and more consistent than configuring the instances manually.

Verify your instance

Connect to your instance via SSH.

$ ssh terraform@$(terraform output -raw public_ip) -i ../tf-packer

Now you have SSH access to your AWS instances without creating an SSH key in AWS. This is useful if your organization maintains keypairs outside of AWS.

Navigate to the Go directory.

$ cd go/src/github.com/hashicorp/learn-go-webapp-demo

Launch the demo webapp.

$ go run webapp.go

In your web browser, navigate your instance's IP address and port 8080 to see the app you deployed.

Destroy your instance

Avoid unnecessary charges in your AWS account by destroying your instance in Terraform.

$ terraform destroy

Type yes when you are prompted in your terminal to delete your infrastructure.

This will not destroy your Packer image. Your Packer image will not incur costs in your AWS account. Most base Linux distributions have free image versions, but be sure to check on the cost of deploying and maintaining your images.

Next Steps

In this tutorial, you created a Packer image with your desired configuration and deployed it using Terraform.

  • To learn about creating deployment scripts for Terraform, visit the cloud-init tutorial.
  • For more information about creating images with Packer, visit the Packer tutorials.
 Previous
 Next

This tutorial also appears in:

  •  
    2 tutorials
    Manage Virtual Machine Images
    Deploy and manage virtual machine images with Terraform and Packer.
    • Terraform
  •  
    16 tutorials
    Use Cases for Terraform
    Use Terraform to perform common operations with other technologies, including Consul, Vault, Packer, and Kubernetes.
    • Terraform
  •  
    16 tutorials
    HashiCorp Products - Better Together
    Use Terraform with other Hashicorp products including Vault, Boundary, Consul, Packer, and Hashicorp Cloud Platform.
    • Terraform
  •  
    25 tutorials
    Associate Tutorial List (002)
    Study for the Terraform Associate (002) exam by following these tutorials. Login to Learn and bookmark them to track your progress. Study the complete list of study materials (including docs) in the Certification Prep guides.
    • Terraform

On this page

  1. Provision Infrastructure with Packer
  2. Prerequisites
  3. Create a local SSH key
  4. Review the shell script
  5. Review the Packer image
  6. Build your Packer image
  7. Deploy your Packer image with Terraform
  8. Verify your instance
  9. Destroy your instance
  10. Next Steps
Give Feedback(opens in new tab)
  • Certifications
  • System Status
  • Terms of Use
  • Security
  • Privacy
  • Trademark Policy
  • Trade Controls
  • Give Feedback(opens in new tab)