2013-07-30 22:17:58 -07:00
---
2020-03-18 18:46:47 -04:00
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.
page_title: Amazon chroot - Builders
2020-04-02 19:39:47 -04:00
sidebar_title: chroot
2016-09-04 12:15:01 -07:00
---
2013-07-30 22:17:58 -07:00
# AMI Builder (chroot)
Type: `amazon-chroot`
2015-07-22 19:31:00 -07:00
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
2016-01-14 15:31:19 -05:00
documentation](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ComponentsAMIs.html#storage-for-the-root-device).
2013-07-30 22:17:58 -07:00
2015-07-22 19:31:00 -07:00
The difference between this builder and the `amazon-ebs` builder is that this
2018-10-26 17:02:51 -07:00
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.
2013-07-30 22:17:58 -07:00
2020-03-23 20:02:12 -04:00
~> **This is an advanced builder** If you're just getting started with
2015-07-22 19:31:00 -07:00
Packer, we recommend starting with the [amazon-ebs
2020-03-31 17:40:07 -04:00
builder](/docs/builders/amazon-ebs), which is much easier to use.
2013-07-30 22:17:58 -07:00
2020-03-18 18:46:47 -04:00
The builder does _not_ manage AMIs. Once it creates an AMI and stores it in
2018-10-26 17:02:51 -07:00
your account, it is up to you to use, delete, etc., the AMI.
2013-07-30 22:17:58 -07:00
2019-06-18 17:05:10 +02:00
### How Does it Work?
2013-07-30 22:17:58 -07:00
2015-07-22 19:31:00 -07:00
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
2016-01-14 15:31:19 -05:00
[chroot](https://en.wikipedia.org/wiki/Chroot) is used to provision the system
2018-10-26 17:02:51 -07:00
within that volume. After provisioning, the volume is detached, snapshotted,
and an AMI is made.
2013-07-30 22:17:58 -07:00
2018-10-26 17:02:51 -07:00
Using this process, minutes can be shaved off the AMI creation process because
a new EC2 instance doesn't need to be launched.
2013-07-30 22:17:58 -07:00
2015-07-22 19:31:00 -07:00
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
2018-10-26 17:02:51 -07:00
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.
2013-07-30 22:17:58 -07:00
2019-06-18 17:05:10 +02:00
## Chroot Specific Configuration Reference
2013-07-30 22:17:58 -07:00
2019-06-18 17:05:10 +02:00
There are many configuration options available for the builder. In addition to
the items listed here, you will want to look at the general configuration
references for [AMI](#ami-configuration),
[BlockDevices](#block-devices-configuration) and
2019-11-06 01:15:19 -08:00
[Access](#access-config-configuration) configuration references, which are
2019-06-18 17:05:10 +02:00
necessary for this build to succeed and can be found further down the page.
2013-07-30 22:17:58 -07:00
2019-06-18 17:05:10 +02:00
#### Required:
2013-07-30 22:17:58 -07:00
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/chroot/Config-required.mdx'
2013-07-30 22:17:58 -07:00
2019-06-18 17:05:10 +02:00
#### Optional:
2020-03-18 18:46:47 -04:00
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/chroot/Config-not-required.mdx'
2019-06-18 17:05:10 +02:00
## General Common Configuration Reference
Following will be a set of fields that are also settable for other aws
builders.
### AMI Configuration
2019-08-26 16:56:57 +02:00
#### Required:
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/common/AMIConfig-required.mdx'
2019-08-26 16:56:57 +02:00
2019-06-18 17:05:10 +02:00
#### Optional:
2020-03-18 18:46:47 -04:00
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/common/AMIConfig-not-required.mdx'
2019-06-18 17:05:10 +02:00
### Block Devices Configuration
Block devices can be nested in the
[ami_block_device_mappings](#ami_block_device_mappings) array.
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/common/BlockDevice.mdx'
2019-06-18 17:05:10 +02:00
#### Optional:
2020-03-18 18:46:47 -04:00
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/common/BlockDevice-not-required.mdx'
2019-06-18 17:05:10 +02:00
2019-11-06 01:15:19 -08:00
### Access Config Configuration
2019-06-18 17:05:10 +02:00
#### Required:
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/common/AccessConfig-required.mdx'
2019-06-18 17:05:10 +02:00
#### Optional:
2020-03-23 20:02:12 -04:00
@include 'builder/amazon/common/AccessConfig-not-required.mdx'
2019-02-05 14:19:24 -08:00
2020-09-22 16:58:56 -07:00
### Assume Role Configuration
@include 'builder/amazon/common/AssumeRoleConfig.mdx'
@include 'builder/amazon/common/AssumeRoleConfig-not-required.mdx'
2020-08-17 17:09:19 +02:00
### Polling Configuration
@include 'builder/amazon/common/AWSPollingConfig.mdx'
@include 'builder/amazon/common/AWSPollingConfig-not-required.mdx'
2013-07-30 22:17:58 -07:00
## Basic Example
Here is a basic example. It is completely valid except for the access keys:
2020-06-16 16:45:53 +02:00
<Tabs>
<Tab heading="JSON">
2020-03-12 10:05:08 -04:00
```json
2013-07-30 22:17:58 -07:00
{
"type": "amazon-chroot",
"access_key": "YOUR KEY HERE",
"secret_key": "YOUR SECRET KEY HERE",
"source_ami": "ami-e81d5881",
2013-08-08 16:59:42 -07:00
"ami_name": "packer-amazon-chroot {{timestamp}}"
2013-07-30 22:17:58 -07:00
}
2014-10-20 13:55:16 -04:00
```
2013-07-30 22:17:58 -07:00
2020-06-16 16:45:53 +02:00
</Tab>
<Tab heading="HCL2">
```hcl
2020-07-17 13:32:09 -07:00
// To make Packer read these variables from the environment into the var object,
// set the environment variables to have the same name as the declared
// variables, with the prefix PKR_VAR_.
2021-01-15 09:18:39 -08:00
// There are other ways to [set variables](/docs/templates/hcl_templates/variables#assigning-values-to-build-variables), including from a var
2020-07-21 02:28:01 -07:00
// file or as a command argument.
2020-07-17 13:32:09 -07:00
// export PKR_VAR_aws_access_key=$YOURKEY
2020-06-16 16:45:53 +02:00
variable "aws_access_key" {
type = string
2020-07-20 17:56:41 -07:00
// default = "hardcoded_key" // Not recommended !
2020-06-16 16:45:53 +02:00
}
2020-07-17 13:32:09 -07:00
// export PKR_VAR_aws_secret_key=$YOURSECRETKEY
2020-06-16 16:45:53 +02:00
variable "aws_secret_key" {
type = string
2020-07-20 17:58:05 -07:00
// default = "hardcoded_secret_key" // Not recommended !
2020-06-16 16:45:53 +02:00
}
source "amazon-chroot" "basic-example" {
access_key = var.aws_access_key
secret_key = var.aws_secret_key
2020-07-17 13:32:09 -07:00
ami_name = "example-chroot"
2020-06-16 16:45:53 +02:00
source_ami = "ami-e81d5881"
}
build {
2020-07-17 13:32:09 -07:00
sources = [
"source.amazon-chroot.basic-example"
]
2020-06-16 16:45:53 +02:00
}
```
</Tab>
</Tabs>
2013-07-30 22:17:58 -07:00
## Chroot Mounts
2016-10-15 14:42:36 +02:00
The `chroot_mounts` configuration can be used to mount specific devices within
2015-07-22 19:31:00 -07:00
the chroot. By default, the following additional mounts are added into the
chroot by Packer:
2013-07-30 22:17:58 -07:00
2020-03-18 18:46:47 -04:00
- `/proc` (proc)
- `/sys` (sysfs)
- `/dev` (bind to real `/dev`)
- `/dev/pts` (devpts)
- `/proc/sys/fs/binfmt_misc` (binfmt_misc)
2013-07-30 22:17:58 -07:00
2020-07-17 13:32:09 -07:00
These default mounts are usually good enough for anyone and are reasonable
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
2018-02-06 19:58:54 -07:00
mounts `/proc` and `/dev`:
2013-07-30 22:17:58 -07:00
2020-07-17 13:32:09 -07:00
<Tabs>
<Tab heading="JSON">
2020-03-12 10:05:08 -04:00
```json
2020-07-17 13:32:09 -07:00
...
"builders": [{
"type": "amazon-chroot"
...
2013-07-30 22:17:58 -07:00
"chroot_mounts": [
["proc", "proc", "/proc"],
["bind", "/dev", "/dev"]
]
2020-07-17 13:32:09 -07:00
}]
```
</Tab>
<Tab heading="HCL2">
```hcl
source "amazon-chroot" "basic-example" {
// ... other builder options
chroot_mounts = [
["proc", "proc", "/proc"],
["bind", "/dev", "/dev"]
]
2013-07-30 22:17:58 -07:00
}
2014-10-20 13:55:16 -04:00
```
2013-07-30 22:17:58 -07:00
2020-07-17 13:32:09 -07:00
</Tab>
</Tabs>
2015-07-22 19:31:00 -07:00
`chroot_mounts` is a list of a 3-tuples of strings. The three components of the
3-tuple, in order, are:
2013-07-30 22:17:58 -07:00
2020-03-18 18:46:47 -04:00
- The filesystem type. If this is "bind", then Packer will properly bind the
filesystem to another mount point.
2013-07-30 22:17:58 -07:00
2020-03-18 18:46:47 -04:00
- The source device.
2013-07-30 22:17:58 -07:00
2020-03-18 18:46:47 -04:00
- The mount directory.
2013-07-30 22:17:58 -07:00
## Parallelism
2020-03-18 18:46:47 -04:00
A quick note on parallelism: it is perfectly safe to run multiple _separate_
2015-07-22 19:31:00 -07:00
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.
2013-07-30 22:17:58 -07:00
2015-07-22 19:31:00 -07:00
Packer properly obtains a process lock for the parallelism-sensitive parts of
its internals such as finding an available device.
2013-09-25 00:09:10 -05:00
2013-11-22 00:11:40 -06:00
## Gotchas
2018-05-23 09:58:15 -07:00
### Unmounting the Filesystem
2018-10-26 17:02:51 -07:00
2013-11-22 00:11:40 -06:00
One of the difficulties with using the chroot builder is that your provisioning
2018-10-26 17:02:51 -07:00
scripts must not leave any processes running or packer will be unable to
unmount the filesystem.
2013-11-22 00:11:40 -06:00
2015-07-22 19:31:00 -07:00
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:
2013-11-22 00:11:40 -06:00
2020-07-17 13:32:09 -07:00
<Tabs>
<Tab heading="JSON">
2020-03-12 10:05:08 -04:00
```json
2020-07-17 13:32:09 -07:00
"provisioners": [
{
"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"]
}
]
```
</Tab>
<Tab heading="HCL2">
```hcl
2014-10-20 13:55:16 -04:00
// ...
2020-07-17 13:32:09 -07:00
build {
sources = [
"source.amazon-chroot.basic-example"
]
2014-10-20 13:55:16 -04:00
2020-07-17 13:32:09 -07:00
// Set policy
provisioner "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"
]
}
// Un-set policy
provisioner "shell" {
inline = ["rm -f /usr/sbin/policy-rc.d"]
}
}
2014-10-20 13:55:16 -04:00
```
2016-09-03 12:06:40 -07:00
2020-07-17 13:32:09 -07:00
</Tab>
</Tabs>
2019-01-03 10:21:41 -08:00
### Ansible provisioner
2019-02-11 11:40:56 -08:00
Running ansible against `amazon-chroot` requires changing the Ansible
connection to chroot and running Ansible as root/sudo.
2019-01-03 10:21:41 -08:00
2018-05-23 09:58:15 -07:00
### Using Instances with NVMe block devices.
2018-10-26 17:02:51 -07:00
2018-05-23 09:58:15 -07:00
In C5, C5d, M5, and i3.metal instances, EBS volumes are exposed as NVMe block
2018-10-26 17:02:51 -07:00
devices
[reference](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html).
2018-05-23 09:58:15 -07:00
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:
2020-07-17 13:32:09 -07:00
<Tabs>
<Tab heading="JSON">
2020-03-12 10:05:08 -04:00
```json
{
"variables": {
2020-03-18 18:46:47 -04:00
"region": "us-east-2"
2020-03-12 10:05:08 -04:00
},
"builders": [
2018-05-23 09:58:15 -07:00
{
2020-03-12 10:05:08 -04:00
"type": "amazon-chroot",
"region": "{{user `region`}}",
"source_ami_filter": {
"filters": {
2020-03-18 18:46:47 -04:00
"virtualization-type": "hvm",
"name": "amzn-ami-hvm-*",
"root-device-type": "ebs"
2020-03-12 10:05:08 -04:00
},
"owners": ["137112412989"],
"most_recent": true
2018-05-23 09:58:15 -07:00
},
2020-03-12 10:05:08 -04:00
"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"]
2018-05-23 09:58:15 -07:00
}
2020-03-12 10:05:08 -04:00
]
}
```
2018-05-23 09:58:15 -07:00
2020-07-17 13:32:09 -07:00
</Tab>
<Tab heading="HCL2">
```hcl
// export PKR_VAR_aws_access_key=$YOURKEY
variable "aws_access_key" {
type = string
}
// export PKR_VAR_aws_secret_key=$YOURSECRETKEY
variable "aws_secret_key" {
type = string
}
source "amazon-chroot" "basic-example" {
access_key = var.aws_access_key
2020-07-20 17:57:11 -07:00
secret_key = var.aws_secret_key
region = "us-east-1"
2020-07-17 13:32:09 -07:00
source_ami_filter {
filter {
key = "virtualization-type"
value = "hvm"
}
filter {
key = "name"
value = "amzn-ami-hvm-*"
}
filter {
key = "root-device-type"
value = "ebs"
}
owners = ["137112412989"]
most_recent = true
}
ena_support = true
ami_name = "amazon-chroot-test-{{timestamp}}"
nvme_device_path = "/dev/nvme1n1p"
device_path = "/dev/sdf"
}
build {
sources = [
"source.amazon-chroot.basic-example"
]
provisioner "shell" {
inline = ["echo Test > /tmp/test.txt"]
}
}
```
</Tab>
</Tabs>
2018-05-23 09:58:15 -07:00
Note that in the `nvme_device_path` you must end with the `p`; if you try to
2018-10-18 19:09:49 -04:00
define the partition in this path (e.g. `nvme_device_path`: `/dev/nvme1n1p1`)
2018-05-23 09:58:15 -07:00
and haven't also set the `"mount_partition": 0`, a `1` will be appended to the
`nvme_device_path` and Packer will fail.
2016-09-04 12:15:01 -07:00
## Building From Scratch
2016-09-03 12:06:40 -07:00
2016-09-04 12:15:01 -07:00
This example demonstrates the essentials of building an image from scratch. A
2016-09-03 12:06:40 -07:00
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
2016-09-04 12:15:01 -07:00
HVM image and format it ext4. This builder block should be followed by
2016-09-03 12:06:40 -07:00
provisioning commands to install the os and bootloader.
2020-07-17 13:32:09 -07:00
<Tabs>
<Tab heading="JSON">
2020-03-12 10:05:08 -04:00
```json
2016-09-03 12:06:40 -07:00
{
"type": "amazon-chroot",
2017-03-18 17:37:02 -07:00
"ami_name": "packer-from-scratch {{timestamp}}",
2016-09-03 12:06:40 -07:00
"from_scratch": true,
"ami_virtualization_type": "hvm",
2017-02-22 10:32:49 -08:00
"pre_mount_commands": [
2016-09-04 12:15:01 -07:00
"parted {{.Device}} mklabel msdos mkpart primary 1M 100% set 1 boot on print",
2016-09-03 12:06:40 -07:00
"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"
}
]
}
```
2018-04-02 19:32:14 +02:00
2020-07-17 13:32:09 -07:00
</Tab>
<Tab heading="HCL2">
```hcl
// This example assumes that AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID are
// set in your environment, or a ~/.aws/credentials file is configured.
source "amazon-chroot" "basic-example" {
region = "us-east-1"
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 {
sources = [
"source.amazon-chroot.basic-example"
]
provisioner "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"
]
}
provisioner "shell" {
inline = ["rm -f /usr/sbin/policy-rc.d"]
}
}
```
</Tab>
</Tabs>
2018-04-02 19:32:14 +02:00
## Build template data
2018-10-26 17:02:51 -07:00
In configuration directives marked as a template engine above, the following
variables are available:
2018-04-02 19:32:14 +02:00
2020-03-18 18:46:47 -04:00
- `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.
2020-05-22 07:17:38 -04:00
- `SourceAMICreationDate` - The source AMI creation date (for example `"2020-05-14T19:26:34.000Z"`).
2020-03-18 18:46:47 -04:00
- `SourceAMIName` - The source AMI Name (for example
`ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to
build the AMI.
- `SourceAMIOwner` - The source AMI owner ID.
- `SourceAMIOwnerName` - The source AMI owner alias/name (for example `amazon`).
- `SourceAMITags` - The source AMI Tags, as a `map[string]string` object.
2020-01-28 14:58:05 +01:00
2020-06-29 13:44:57 +02:00
## Build Shared Information Variables
2020-01-28 14:58:05 +01:00
2021-01-15 09:18:39 -08:00
This builder generates data that are shared with provisioner and post-processor via build function of [template engine](/docs/templates/engine) for JSON and [contextual variables](/docs/templates/hcl_templates/contextual-variables) for HCL2.
2020-06-29 13:44:57 +02:00
The generated variables available for this builder are:
2020-01-28 14:58:05 +01:00
2020-08-12 01:43:15 -07:00
- `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.
- `SourceAMICreationDate` - The source AMI creation date (for example `"2020-05-14T19:26:34.000Z"`).
2020-03-18 18:46:47 -04:00
- `SourceAMIName` - The source AMI Name (for example
`ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to
build the AMI.
2020-08-12 01:43:15 -07:00
- `SourceAMIOwner` - The source AMI owner ID.
- `SourceAMIOwnerName` - The source AMI owner alias/name (for example `amazon`).
2020-03-18 18:46:47 -04:00
- `Device` - Root device path.
- `MountPath` - Device mounting path.
2020-06-29 13:44:57 +02:00
Usage example:
<Tabs>
<Tab heading="JSON">
```json
"post-processors": [
{
"type": "manifest",
"output": "manifest.json",
"strip_path": true,
"custom_data": {
"source_ami_name": "{{ build `SourceAMIName` }}",
"device": "{{ build `Device` }}",
"mount_path": "{{ build `MountPath` }}"
}
}
]
```
</Tab>
<Tab heading="HCL2">
```hcl
2020-10-22 00:42:45 -07:00
// When accessing one of these variables from inside the builder, you need to
// use the golang templating syntax. This is due to an architectural quirk that
// won't be easily resolvable until legacy json templates are deprecated:
{
source "amazon-ebs" "basic-example" {
tags = {
OS_Version = "Ubuntu"
Release = "Latest"
Base_AMI_ID = "{{ .SourceAMI }}"
Base_AMI_Name = "{{ .SourceAMIName }}"
}
}
// when accessing one of the variables from a provisioner or post-processor, use
// hcl-syntax
2020-06-29 13:44:57 +02:00
post-processor "manifest" {
output = "manifest.json"
strip_path = true
custom_data = {
source_ami_name = "${build.SourceAMIName}"
device = "${build.Device}"
mount_path = "${build.MountPath}"
}
}
```
</Tab>
</Tabs>