Skip to content
Packer plugin to build ARM images
Branch: master
Clone or download
mkaczanowski Merge pull request #3 from ipl31/chroot_error
add /usr/sbin to chroot_env in raspian.json
Latest commit 1826b54 Dec 14, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github/workflows Create archlinuxarm-odroid-xu4.yml Nov 22, 2019
boards add /usr/sbin to chroot_env in raspian.json Dec 13, 2019
builder fix extension bug Nov 22, 2019
config lint Nov 19, 2019
.gitignore add docker example Nov 20, 2019
.travis.yml Update .travis.yml Nov 18, 2019
LICENSE Create LICENSE Nov 17, 2019 upd documentation Dec 12, 2019
go.mod support multiple methods Nov 15, 2019
go.sum support multiple methods Nov 15, 2019
main.go steps implementation Nov 6, 2019

Packer builder ARM

Build Status GoDoc GoReportCard

This plugin allows you to build or extend ARM system image. It operates in two modes:

  • new - creates empty disk image and populates the rootfs on it
  • reuse - uses already existing image as the base

Plugin mimics standard image creation process, such as:

  • builing base empty image (dd)
  • partitioning (sgdisk / sfdisk)
  • filesystem creation (mkfs.type)
  • partition mapping (losetup)
  • filesystem mount (mount)
  • populate rootfs (tar/unzip/xz etc)
  • setup qemu + chroot
  • customize installation within chroot

The virtualization works via binfmt_misc kernel feature and qemu.

Since the setup varies a lot for different hardware types, the example configuration is available per "board". Currently the following boards are supported (feel free to add more):

  • bananapi-r1 (Archlinux ARM)
  • beaglebone-black (Archlinux ARM, Debian)
  • jetson-nano (Ubuntu)
  • odroid-u3 (Archlinux ARM)
  • odroid-xu4 (Archlinux ARM, Ubuntu)
  • parallella (Ubuntu)
  • raspberry-pi (Archlinux ARM, Raspbian)
  • wandboard (Archlinux ARM)

Quick start

git clone
cd packer-builder-arm
go mod download
go build

sudo packer build boards/odroid-u3/archlinuxarm.json


  • sfdisk / sgdisk
  • e2fsprogs


Configuration is split into 3 parts:

  • remote file config
  • image config
  • qemu config

Remote file

Describes the remote file that is going to be used as base image or rootfs archive (depending on image_build_method)

"file_urls" : [""],
"file_checksum_url": "",
"file_checksum_type": "md5",
"file_unarchive_cmd": ["bsdtar", "-xpf", "$ARCHIVE_PATH", "-C", "$MOUNTPOINT"],
"file_target_extension": "tar.gz",

The file_unarchive_cmd is optional and should be used if the standard golang archiver can't handle the archive format.

Image config

The base image description (size, partitions, mountpoints etc).

"image_build_method": "new",
"image_path": "odroid-xu4.img",
"image_size": "2G",
"image_type": "dos",
"image_partitions": [
        "name": "root",
        "type": "8300",
        "start_sector": "4096",
        "filesystem": "ext4",
        "size": "0",
        "mountpoint": "/"

The plugin doesn't try to detect the image partitions because that varies a lot. Instead it solely depend on image_partitions specification, so you should set that even if you reuse the image (method = reuse).

Qemu config

Anything qemu related:

"qemu_binary_source_path": "/usr/bin/qemu-arm-static",
"qemu_binary_destination_path": "/usr/bin/qemu-arm-static"

Chroot provisioner

To execute command within chroot environment you should use chroot communicator:

"provisioners": [
   "type": "shell",
   "inline": [
     "pacman-key --init",
     "pacman-key --populate archlinuxarm"


To dump image on device you can use custom postprocessor (really wrapper around dd with some sanity checks):

"post-processors": [
     "type": "flasher",
     "device": "/dev/sdX",
     "block_size": "4096",
     "interactive": true


Generating rootfs archive

While image (.img) format is useful for most cases, you might want to use rootfs for other purposes (ex. export to docker). This is how you can generate rootfs archive instead of image:

"image_path": "odroid-xu4.img" # generates image
"image_path": "odroid-xu4.img.tar.gz" # generates rootfs archive


With artifice plugin you can pass rootfs archive to docker plugins

"post-processors": [
        "type": "artifice",
        "files": ["rootfs.tar.gz"]
        "type": "docker-import",
        "repository": "mkaczanowski/archlinuxarm",
        "tag": "latest"


This is the live example on how to use github actions to push image to docker image registry:

cat .github/workflows/archlinuxarm-armv7-docker.yml

How is this plugin different from solo-io/packer-builder-arm-image


For more examples please see:

tree boards/



You can’t perform that action at this time.