Packer’s ability to bake AMIs within your own VPC and subnets is less about convenience and more about control over your build environment.

Let’s see it in action. Imagine you have a specific network setup for your build infrastructure – perhaps a hardened subnet with restricted egress, or a subnet designed for high-speed access to internal artifact repositories. Packer can be told to launch its temporary builder instances there.

{
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "us-east-1",
      "instance_type": "t3.micro",
      "ssh_username": "ec2-user",

      "ami_name": "my-custom-vpc-ami-{{timestamp}}",

      "vpc_id": "vpc-0123456789abcdef0",
      "subnet_id": "subnet-0abcdef1234567890",
      "security_group_id": "sg-0123456789abcdef0"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "echo 'Hello from a custom network!'"
      ]
    }
  ]
}

Here, vpc_id, subnet_id, and security_group_id are the key parameters. When Packer initiates the EC2 instance for building, it will use these specific identifiers to place the instance within your designated network. This means the instance gets the IP address, routing, and security posture defined by your VPC configuration.

The core problem this solves is the default behavior of Packer launching build instances in a default VPC or a randomly assigned subnet. This default can be problematic for several reasons:

  • Security Compliance: Your organization might mandate that all compute instances, including build agents, reside within specific, audited network segments. Using default networks bypasses these controls.
  • Network Access: Your build process might require access to internal resources (like artifact repositories, licensing servers, or internal APIs) that are only reachable from specific subnets. By launching in a custom subnet, Packer ensures the builder instance has the correct network routes and security group rules to reach these resources.
  • Predictability and Reproducibility: Relying on default networks introduces an element of randomness. By specifying your VPC and subnet, you ensure that your build environment is consistent and predictable, reducing "it worked on my machine" scenarios that stem from network differences.
  • Cost and Performance Optimization: You might have dedicated, high-bandwidth subnets for build tasks to accelerate the download of base images and dependencies.

Internally, when Packer’s amazon-ebs builder is configured with vpc_id and subnet_id, it doesn’t just launch a generic EC2 instance. It passes these parameters directly to the EC2 RunInstances API call. The AWS API then handles the provisioning of the instance within the specified network enclosure. The security_group_id ensures that the instance can communicate over SSH (typically on port 22) to allow Packer to provision it, and that it can access any other resources it needs according to your security policies.

The primary levers you control are the identifiers for your VPC, subnet, and security group. These are static resources within your AWS account. You’ll need to know these IDs beforehand. You can find them in the AWS Management Console under VPC -> Your VPCs, Subnets, and Security Groups.

When you specify a security_group_id that doesn’t allow inbound SSH (port 22) from your current IP address, Packer will fail to connect to the instance, and you’ll see an SSH timeout error.

The next step is to integrate this custom network build process into your CI/CD pipeline, ensuring your AMIs are always built in a controlled and compliant environment.

Want structured learning?

Take the full Packer course →