{"id":13464051,"url":"https://github.com/solo-io/packer-plugin-arm-image","last_synced_at":"2025-04-14T20:54:23.923Z","repository":{"id":38846933,"uuid":"115292323","full_name":"solo-io/packer-plugin-arm-image","owner":"solo-io","description":"Packer plugin for ARM images","archived":false,"fork":false,"pushed_at":"2024-11-12T14:32:45.000Z","size":22660,"stargazers_count":433,"open_issues_count":23,"forks_count":106,"subscribers_count":39,"default_branch":"master","last_synced_at":"2025-04-07T16:09:11.874Z","etag":null,"topics":["arm-images","packer-plugin","packer-provisioner","qemu-system-arm","raspberry-pi"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/solo-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-12-24T23:32:48.000Z","updated_at":"2025-03-22T14:07:29.000Z","dependencies_parsed_at":"2024-05-28T17:05:17.686Z","dependency_job_id":"dea33d81-9f43-422b-9c7d-cc9826c5ec00","html_url":"https://github.com/solo-io/packer-plugin-arm-image","commit_stats":{"total_commits":161,"total_committers":49,"mean_commits":"3.2857142857142856","dds":0.4347826086956522,"last_synced_commit":"e1ace42451b208497fa4cc5c26084408a1f1269a"},"previous_names":["solo-io/packer-builder-arm-image"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solo-io%2Fpacker-plugin-arm-image","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solo-io%2Fpacker-plugin-arm-image/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solo-io%2Fpacker-plugin-arm-image/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solo-io%2Fpacker-plugin-arm-image/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solo-io","download_url":"https://codeload.github.com/solo-io/packer-plugin-arm-image/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248961085,"owners_count":21189990,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arm-images","packer-plugin","packer-provisioner","qemu-system-arm","raspberry-pi"],"created_at":"2024-07-31T14:00:32.948Z","updated_at":"2025-04-14T20:54:23.876Z","avatar_url":"https://github.com/solo-io.png","language":"Go","funding_links":[],"categories":["Go","raspberry-pi"],"sub_categories":[],"readme":"# Packer plugin for ARM images\n\nThis plugin lets you take an existing ARM image and modify it on your x86 machine.\nIt is optimized for raspberry pi use case - MBR partition table, with the file system partition\nbeing the last partition.\n\nWith this plugin, you can:\n\n- Provision new ARM images from existing ones\n- Use ARM binaries for provisioning (`apt-get install` for example)\n- Resize the last partition (the filesystem partition in the raspberry pi) in case you need more\n  space than the default.\n\nTested for Raspbian images built on Ubuntu 19.10. It is based partly on the chroot AWS\nprovisioner, though the code was copied to prevent AWS dependencies.\n\n## How it works\n\nThe plugin runs the provisioners in a chroot environment.  Binary execution is done using\n`qemu-arm-static`, via `binfmt_misc`.\n\n### Dependencies\n\nThis builder uses the following shell commands:\n\n- `qemu-user-static` - Executing arm binaries. This is optional as the released binary can use embedded versions of `qemu-aarch64-static` and `qemu-arm-static`. If you have one installed, it will be used instead of the embedded ones.\n- `losetup` - To mount the image. This command is pre-installed in most distributions.\n\nTo install the needed binaries on derivatives of the Debian Linux variant:\n\n```shell\nsudo apt install qemu-user-static\n```\n\nFedora:\n\n```shell\nsudo dnf install qemu-user-static\n```\n\nArchlinux:\n\n```shell\npacman -S qemu-arm-static\n```\n\nOther commands that are used are (that should already be installed) : mount, umount, cp, ls, chroot.\n\nTo resize the filesystem, the following commands are used:\n\n- `e2fsck`\n- `resize2fs`\n\nTo provide custom arguments to `qemu-arm-static` using the `qemu_args` config, `gcc` is required (to compile a C wrapper).\n\nNote: resizing is only supported for the last active\npartition in an MBR partition table (as there is no need to move things).\n\nThis plugin uses the following kernel feature:\n\n- support for `/proc/sys/fs/binfmt_misc` so that ARM binaries are automatically executed with qemu\n\n### Operation\n\nThis provisioner allows you to run packer provisioners on your ARM image locally. It does so by mounting the image on to the local file system, and then using `chroot` combined with `binfmt_misc` to the provisioners in a simulated ARM environment.\n\n## Configuration\n\nTo use, you need to provide an existing image that we will then modify. We re-use packer's support\nfor downloading ISOs (though the image should not be an ISO file).\nSupporting also zipped images (enabling you downloading official raspbian images directly).\n\nSee [raspbian_golang.json](samples/raspbian_golang.json) and [config.go](pkg/builder/config.go) for details.\nFor configuration reference, see the [builder doc](docs/builders/arm-image.mdx).\n\n*Note* if your image is arm64, set `qemu_binary` to `qemu-aarch64-static` in your configuration json file.\n\n## Compiling and Testing\n\n### Building\n\nAs this tool performs low-level OS manipulations - consider using a VM to run this code for isolation. While this is recommended, it is not mandatory.\n\nThis project uses [go modules](https://github.com/golang/go/wiki/Modules) for dependencies introduced in Go 1.11.\nTo build:\n\n```bash\ngit clone https://github.com/solo-io/packer-plugin-arm-image\ncd packer-plugin-arm-image\ngo mod download\ngo build\n```\n\n### Running with Vagrant\n\nThis project includes a Vagrant file and helper script that build a VM run time environment. The run time environment has\ncustom provisions to build an image in an iterative fashion (thanks to @tommie-lie for adding this feature).\n\nTo use the Vagrant environment, run the following commands:\n\n```shell\ngit clone https://github.com/solo-io/packer-plugin-arm-image\ncd packer-plugin-arm-image\nvagrant up\n```\n\nTo build an image edit [samples/raspbian_golang.json](samples/raspbian_golang.json) (or set `PACKERFILE` to point to your json config), and use `vagrant provision` like so:\n\n```shell\nvagrant provision --provision-with build-image\n```\n\nThe example config produces an image with go installed and extends the filesystem by 1GB.\n\nThat's it! Flash it and run!\n\n### Running locally\n\nThis builder requires root permissions as it performs low level machine operations. To run it locally,\nyou can set `PACKER_CONFIG_DIR` back to your local home before sudo-ing to packer. For example:\n\n```shell\nPACKER_CONFIG_DIR=$HOME sudo -E $(which packer) build .\n```\n\n### Running with Docker\n\n#### Prerequisites\n\nDocker needs capability of creating new devices on host machine, so it can create `/dev/loop*` and mount image into it. While it may be possible to accomplish with multiple `--device-cgroup-rule` and `--add-cap`, it's much easier to use `--privileged` flag to accomplish that. Even so, it is considered bad practice to do so, do it with extra precautions. Also because of those requirements rootless will not work for this container.\n\n#### Option 1: Clone this repo and build the Docker image locally\n\nBuild the Docker image locally\n\n```shell\ndocker build -t packer-builder-arm .\n```\n\nBuild the `samples/raspbian_golang.json` Packer image\n\n```shell\ndocker run \\\n  --rm \\\n  --privileged \\\n  -v /dev:/dev \\\n  -v ${PWD}:/build:ro \\\n  -v ${PWD}/packer_cache:/build/packer_cache \\\n  -v ${PWD}/output-arm-image:/build/output-arm-image \\\n  -e PACKER_CACHE_DIR=/build/packer_cache \\\n  packer-builder-arm build samples/raspbian_golang.json\n```\n\n#### Option 2: Run the published Docker image\n\nAlternatively, you can use the `ghcr.io/solo-io/packer-plugin-arm-image` that's built off latest master without needing to clone this repository.\n\n```shell\ndocker run \\\n  --rm \\\n  --privileged \\\n  -v /dev:/dev \\\n  -v ${PWD}:/build:ro \\\n  -v ${PWD}/packer_cache:/build/packer_cache \\\n  -v ${PWD}/output-arm-image:/build/output-arm-image \\\n  ghcr.io/solo-io/packer-plugin-arm-image build samples/raspbian_golang.json\n```\n\nThat's it, flash it and run!\n\n### Running Standalone\n\n```shell\npacker build samples/raspbian_golang.json\n```\n\n## Flashing\n\nWe have a post-processor stage for flashing.\n\n### Golang flasher\n\n```shell\ngo build cmd/flasher/main.go\n```\n\nIt will auto-detect most things and guides you with questions.\n\n### dd\n\n(Tested on MacOS)\n\n```shell\n# find the identifier of the device you want to flash\ndiskutil list\n\n# un-mount the disk\ndiskutil unmountDisk /dev/disk2\n\n# flash the image, go for a coffee\nsudo dd bs=4m if=output-arm-image/image of=/dev/disk2\n\n# eject the disk\ndiskutil eject /dev/disk2\n```\n\n## Cookbook\n\n### Raspberry Pi Provisioners\n\n#### Enable ssh\n\n```json\n{\n  \"type\": \"shell\",\n  \"inline\": [\"touch /boot/ssh\"]\n}\n```\n\n#### Set WiFi password\n\nset the user variables name `wifi_name` and `wifi_password`, then:\n\n```json\n{\n  \"type\": \"shell\",\n  \"inline\": [\n    \"echo 'network={' \u003e\u003e /etc/wpa_supplicant/wpa_supplicant.conf\",\n    \"echo '    ssid=\\\"{{user `wifi_name`}}\\\"' \u003e\u003e /etc/wpa_supplicant/wpa_supplicant.conf\",\n    \"echo '    psk=\\\"{{user `wifi_password`}}\\\"' \u003e\u003e /etc/wpa_supplicant/wpa_supplicant.conf\",\n    \"echo '}' \u003e\u003e /etc/wpa_supplicant/wpa_supplicant.conf\"\n    ]\n}\n```\n\n#### Add ssh key to authorized keys, enable ssh, disable password login\n\nThis example locks down the image to only use your\ncurrent ssh key. Disabling password login makes it extra secure for networked environments.\n\nNote: this example requires you to run the plugin without a VM, as it copies your local ssh key.\n\n```json\n{\n  \"variables\": {\n    \"ssh_key_src\": \"{{env `HOME`}}/.ssh/id_rsa.pub\",\n    \"image_home_dir\": \"/home/pi\"\n  },\n  \"builders\": [\n    {\n      \"type\": \"arm-image\",\n      \"iso_url\": \"https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2017-12-01/2017-11-29-raspbian-stretch-lite.zip\",\n      \"iso_checksum\": \"sha256:e942b70072f2e83c446b9de6f202eb8f9692c06e7d92c343361340cc016e0c9f\"\n    }\n  ],\n  \"provisioners\": [\n    {\n      \"type\": \"shell\",\n      \"inline\": [\n        \"mkdir {{user `image_home_dir`}}/.ssh\"\n      ]\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"{{user `ssh_key_src`}}\",\n      \"destination\": \"{{user `image_home_dir`}}/.ssh/authorized_keys\"\n    },\n    {\n      \"type\": \"shell\",\n      \"inline\": [\n        \"touch /boot/ssh\"\n      ]\n    },\n    {\n      \"type\": \"shell\",\n      \"inline\": [\n        \"sed '/PasswordAuthentication/d' -i /etc/ssh/sshd_config\",\n        \"echo \u003e\u003e /etc/ssh/sshd_config\",\n        \"echo 'PasswordAuthentication no' \u003e\u003e /etc/ssh/sshd_config\"\n      ]\n    }\n  ]\n}\n```\n\n### A complete example\n\nSee everything included in here: [samples/pi-secure-wifi-ssh.json](samples/pi-secure-wifi-ssh.json). Build like so:\n\n```shell\nsudo packer build  -var wifi_name=SSID -var wifi_password=PASSWORD samples/pi-secure-wifi-ssh.json\n# or  if running from vagrant ssh:\nsudo packer build  -var wifi_name=SSID -var wifi_password=PASSWORD /vagrant/samples/pi-secure-wifi-ssh.json\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolo-io%2Fpacker-plugin-arm-image","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolo-io%2Fpacker-plugin-arm-image","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolo-io%2Fpacker-plugin-arm-image/lists"}