Packer Plugin Builder ARM

repository·master·Indexed 43 days ago

https://github.com/mkaczanowski/packer-plugin-builder-arm

A Packer plugin for building or extending ARM-based system images. It supports creating new images, reusing existing ones, or resizing partitions using QEMU and binfmt_misc for cross-architecture emulation. The plugin allows for the configuration of remote files, image partitioning, and QEMU emulation environments, and supports execution of commands in chroot via the standard Packer shell provisioner.

Tokens
2K
Snippets
8
Records
8
Agent score
6%

What's inside Packer Plugin Builder ARM

  1. Declare the ARM plugin in HCL2 templates

    master

    Because this is a multi-component plugin, HCL2 templates must declare it in a required_plugins block so packer init can resolve the correct version.

    packer {
      required_plugins {
        arm = {
          source  = "github.com/mkaczanowski/arm"
          version = ">= 1.0.9"
        }
      }
    }

    Legacy JSON templates using "type": "arm" do not support required_plugins but will work once the plugin is installed via packer plugins install.

    packer {
      required_plugins {
        arm = {
          source  = "github.com/mkaczanowski/arm"
          version = ">= 1.0.9"
        }
      }
    }
  2. Run the plugin in Docker (Recommended for macOS)

    master

    Using Docker is the preferred method for macOS users to avoid issues with qemu-user-static, loop mounting, and missing Linux-specific tools. The container is multi-arch (amd64/arm64).

    Important for Mac users: Do not run go build . locally and then attempt to run the Docker commands from that same folder. This will cause an exec format error because the local binary is a Darwin binary. Delete any local packer-* binaries before using Docker.

    Using the Docker Hub image

    1. Pull the latest image:

      docker pull mkaczanowski/packer-plugin-builder-arm:latest
    2. Build a board:

      docker run --rm --privileged -v /dev:/dev -v ${PWD}:/build mkaczanowski/packer-plugin-builder-arm:latest build boards/raspberry-pi/raspbian.json
    3. Build with extra system packages (e.g., bmap-tools, zstd):

      docker run --rm --privileged -v /dev:/dev -v ${PWD}:/build mkaczanowski/packer-plugin-builder-arm:latest build boards/raspberry-pi/raspbian.json -extra-system-packages=bmap-tools,zstd

    Building the container locally

    1. Build the image:

      docker build -t packer-plugin-builder-arm -f docker/Dockerfile .
    2. Run the local image:

      docker run --rm --privileged -v /dev:/dev -v ${PWD}:/build packer-plugin-builder-arm build boards/raspberry-pi/raspbian.json
    docker run --rm --privileged -v /dev:/dev -v ${PWD}:/build mkaczanowski/packer-plugin-builder-arm:latest build boards/raspberry-pi/raspbian.json
  3. Quick start: Build and register the ARM plugin

    master

    To use the plugin locally, you must build the Go binary and register it with Packer. This is a one-time setup or required whenever you rebuild the plugin.

    1. Build the plugin:

      git clone https://github.com/mkaczanowski/packer-plugin-builder-arm
      cd packer-plugin-builder-arm
      go mod download
      go build -o packer-plugin-builder-arm
    2. Register with Packer:

      packer plugins install --path ./packer-plugin-builder-arm github.com/mkaczanowski/arm
    3. Run a build:

      sudo -E packer build boards/odroid-u3/archlinuxarm.json
    git clone https://github.com/mkaczanowski/packer-plugin-builder-arm
    cd packer-plugin-builder-arm
    go mod download
    go build -o packer-plugin-builder-arm
    
    packer plugins install --path ./packer-plugin-builder-arm github.com/mkaczanowski/arm
    
    sudo -E packer build boards/odroid-u3/archlinuxarm.json
  4. Configure QEMU Emulation

    master

    Use QEMU configuration to specify the emulation environment for the chroot session.

    Key configuration options:

    • qemu_binary_source_path: Path to the QEMU binary.
    • qemu_binary_destination_path: Destination path for the QEMU binary within the chroot.

    Emulating different CPUs: You can control the ARM instruction set being emulated via the QEMU_CPU environment variable. For example, to switch to arm64 or armv6l:

    • Via Packer: QEMU_CPU=arm1176 packer build ...
    • Via Docker: docker run -e QEMU_CPU=arm1176 ...
    "qemu_binary_source_path": "/usr/bin/qemu-arm-static",
    "qemu_binary_destination_path": "/usr/bin/qemu-arm-static"
  5. Configure Remote Files

    master

    The remote file configuration defines the source for the base image or rootfs archive. It uses github.com/hashicorp/go-getter for downloads.

    Key configuration options:

    • file_urls: List of URLs to download (supports local, http(s), etc.).
    • file_checksum_url: URL to the checksum file.
    • file_checksum_type: Type of checksum (e.g., md5).
    • file_unarchive_cmd: (Optional) Command to use if the standard Go archiver fails (e.g., ["bsdtar", "-xpf", "$ARCHIVE_PATH", "-C", "$MOUNTPOINT"]).
    • file_target_extension: Used for raw images (e.g., .img or .iso).
    • file_user_agent: Overrides the default HTTP User-Agent if mirrors reject the default client.
    "file_urls" : ["http://os.archlinuxarm.org/os/ArchLinuxARM-odroid-xu3-latest.tar.gz"],
    "file_checksum_url": "http://hu.mirror.archlinuxarm.org/os/ArchLinuxARM-odroid-xu3-latest.tar.gz.md5",
    "file_checksum_type": "md5",
    "file_unarchive_cmd": ["bsdtar", "-xpf", "$ARCHIVE_PATH", "-C", "$MOUNTPOINT"],
    "file_target_extension": "tar.gz"
  6. Configure Image and Partitioning

    master

    The image configuration defines how the disk image is constructed. The plugin relies entirely on your image_partitions specification for partitioning.

    Key configuration options:

    • image_build_method: One of new (creates empty disk), reuse (uses existing image), or resize (expands existing partition).
    • image_path: The output filename (e.g., odroid-xu4.img). If you append .tar.gz to the path, it generates a rootfs archive instead of a disk image.
    • image_size: Total size of the image (e.g., 2G).
    • image_type: Partition table type (e.g., dos).
    • image_partitions: An array of partition objects. Each object requires:
      • name: Partition name (e.g., root).
      • type: Partition type (e.g., 8300 for Linux).
      • start_sector: Starting sector.
      • filesystem: Filesystem type (e.g., ext4).
      • size: Size of the partition. Set to 0 when using image_build_method: "resize" to trigger expansion of that partition.
    "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": "/"
        }
    ],
  7. Resize an existing partition

    master

    To expand a single ext{2,3,4} partition in an existing image, use the resize build method. You must specify the partition you wish to expand by setting its size to 0.

    Example Configuration:

    "builders": [
      {
        "type": "arm",
        "image_build_method": "resize",
        "image_partitions": [
          {
            "name": "boot",
            "size": "512M"
          },
          {
            "name": "root",
            "size": "0"
          }
        ]
      }
    ]
  8. Execute commands in Chroot via Shell Provisioner

    master

    To run commands inside the ARM chroot environment, use a standard Packer shell provisioner. The plugin handles the communication with the chroot environment automatically.

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