--- description: | The amazon-chroot Packer builder is able to create Amazon AMIs backed by an EBS volume as the root device. For more information on the difference between instance storage and EBS-backed instances, storage for the root device section in the EC2 documentation. layout: docs page_title: 'Amazon chroot - Builders' sidebar_current: 'docs-builders-amazon-chroot' --- # AMI Builder (chroot) Type: `amazon-chroot` The `amazon-chroot` Packer builder is able to create Amazon AMIs backed by an EBS volume as the root device. For more information on the difference between instance storage and EBS-backed instances, see the ["storage for the root device" section in the EC2 documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device). The difference between this builder and the `amazon-ebs` builder is that this builder is able to build an EBS-backed AMI without launching a new EC2 instance. This can dramatically speed up AMI builds for organizations who need the extra fast build. \~> **This is an advanced builder** If you're just getting started with Packer, we recommend starting with the [amazon-ebs builder](/docs/builders/amazon-ebs.html), which is much easier to use. The builder does *not* manage AMIs. Once it creates an AMI and stores it in your account, it is up to you to use, delete, etc., the AMI. ## How Does it Work? This builder works by creating a new EBS volume from an existing source AMI and attaching it into an already-running EC2 instance. Once attached, a [chroot](https://en.wikipedia.org/wiki/Chroot) is used to provision the system within that volume. After provisioning, the volume is detached, snapshotted, and an AMI is made. Using this process, minutes can be shaved off the AMI creation process because a new EC2 instance doesn't need to be launched. There are some restrictions, however. The host EC2 instance where the volume is attached to must be a similar system (generally the same OS version, kernel versions, etc.) as the AMI being built. Additionally, this process is much more expensive because the EC2 instance must be kept running persistently in order to build AMIs, whereas the other AMI builders start instances on-demand to build AMIs as needed. ## Configuration Reference There are many configuration options available for the builder. They are segmented below into two categories: required and optional parameters. Within each category, the available configuration keys are alphabetized. ### Required: <%= partial "partials/builder/amazon/common/AccessConfig-required" %> <%= partial "partials/builder/amazon/chroot/Config-required" %> ### Optional: <%= partial "partials/builder/amazon/chroot/Config-not-required" %> <%= partial "partials/builder/amazon/common/AccessConfig-not-required" %> <%= partial "partials/builder/amazon/common/AMIConfig-not-required" %> <%= partial "partials/builder/amazon/common/AMIBlockDevices-not-required" %> ## Basic Example Here is a basic example. It is completely valid except for the access keys: ``` json { "type": "amazon-chroot", "access_key": "YOUR KEY HERE", "secret_key": "YOUR SECRET KEY HERE", "source_ami": "ami-e81d5881", "ami_name": "packer-amazon-chroot {{timestamp}}" } ``` ## Chroot Mounts The `chroot_mounts` configuration can be used to mount specific devices within the chroot. By default, the following additional mounts are added into the chroot by Packer: - `/proc` (proc) - `/sys` (sysfs) - `/dev` (bind to real `/dev`) - `/dev/pts` (devpts) - `/proc/sys/fs/binfmt_misc` (binfmt\_misc) These default mounts are usually good enough for anyone and are sane defaults. However, if you want to change or add the mount points, you may using the `chroot_mounts` configuration. Here is an example configuration which only mounts `/proc` and `/dev`: ``` json { "chroot_mounts": [ ["proc", "proc", "/proc"], ["bind", "/dev", "/dev"] ] } ``` `chroot_mounts` is a list of a 3-tuples of strings. The three components of the 3-tuple, in order, are: - The filesystem type. If this is "bind", then Packer will properly bind the filesystem to another mount point. - The source device. - The mount directory. ## Parallelism A quick note on parallelism: it is perfectly safe to run multiple *separate* Packer processes with the `amazon-chroot` builder on the same EC2 instance. In fact, this is recommended as a way to push the most performance out of your AMI builds. Packer properly obtains a process lock for the parallelism-sensitive parts of its internals such as finding an available device. ## Gotchas ### Unmounting the Filesystem One of the difficulties with using the chroot builder is that your provisioning scripts must not leave any processes running or packer will be unable to unmount the filesystem. For debian based distributions you can setup a [policy-rc.d](http://people.debian.org/~hmh/invokerc.d-policyrc.d-specification.txt) file which will prevent packages installed by your provisioners from starting services: ``` json { "type": "shell", "inline": [ "echo '#!/bin/sh' > /usr/sbin/policy-rc.d", "echo 'exit 101' >> /usr/sbin/policy-rc.d", "chmod a+x /usr/sbin/policy-rc.d" ] }, // ... { "type": "shell", "inline": [ "rm -f /usr/sbin/policy-rc.d" ] } ``` ### Ansible provisioner Running ansible against `amazon-chroot` requires changing the Ansible connection to chroot and running Ansible as root/sudo. ### Using Instances with NVMe block devices. In C5, C5d, M5, and i3.metal instances, EBS volumes are exposed as NVMe block devices [reference](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html). In order to correctly mount these devices, you have to do some extra legwork, involving the `nvme_device_path` option above. Read that for more information. A working example for mounting an NVMe device is below: { "variables": { "region" : "us-east-2" }, "builders": [ { "type": "amazon-chroot", "region": "{{user `region`}}", "source_ami_filter": { "filters": { "virtualization-type": "hvm", "name": "amzn-ami-hvm-*", "root-device-type": "ebs" }, "owners": ["137112412989"], "most_recent": true }, "ena_support": true, "ami_name": "amazon-chroot-test-{{timestamp}}", "nvme_device_path": "/dev/nvme1n1p", "device_path": "/dev/sdf" } ], "provisioners": [ { "type": "shell", "inline": ["echo Test > /tmp/test.txt"] } ] } Note that in the `nvme_device_path` you must end with the `p`; if you try to define the partition in this path (e.g. `nvme_device_path`: `/dev/nvme1n1p1`) and haven't also set the `"mount_partition": 0`, a `1` will be appended to the `nvme_device_path` and Packer will fail. ## Building From Scratch This example demonstrates the essentials of building an image from scratch. A 15G gp2 (SSD) device is created (overriding the default of standard/magnetic). The device setup commands partition the device with one partition for use as an HVM image and format it ext4. This builder block should be followed by provisioning commands to install the os and bootloader. ``` json { "type": "amazon-chroot", "ami_name": "packer-from-scratch {{timestamp}}", "from_scratch": true, "ami_virtualization_type": "hvm", "pre_mount_commands": [ "parted {{.Device}} mklabel msdos mkpart primary 1M 100% set 1 boot on print", "mkfs.ext4 {{.Device}}1" ], "root_volume_size": 15, "root_device_name": "xvda", "ami_block_device_mappings": [ { "device_name": "xvda", "delete_on_termination": true, "volume_type": "gp2" } ] } ``` ## Build template data In configuration directives marked as a template engine above, the following variables are available: - `BuildRegion` - The region (for example `eu-central-1`) where Packer is building the AMI. - `SourceAMI` - The source AMI ID (for example `ami-a2412fcd`) used to build the AMI. - `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI. - `SourceAMITags` - The source AMI Tags, as a `map[string]string` object.