From 21b5239795f9248a6754ca9b0dd7e2eb10ef7181 Mon Sep 17 00:00:00 2001 From: Tim Ebert Date: Wed, 10 Mar 2021 02:24:18 +0100 Subject: [PATCH] Switch to vagrant, enable cgroups, fix readdir issues --- .gitignore | 1 + README.md | 46 +++++++++++++-------------------- Vagrantfile | 19 ++++++++++++++ bootstrap.sh | 15 +++++++++++ prepare-build.sh => build.sh | 49 +++++++++++++++++++++++++++++++++--- install.sh | 24 ------------------ 6 files changed, 99 insertions(+), 55 deletions(-) create mode 100644 Vagrantfile create mode 100755 bootstrap.sh rename prepare-build.sh => build.sh (79%) delete mode 100755 install.sh diff --git a/.gitignore b/.gitignore index 0303c93..682b4df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.img *.zip +/.vagrant diff --git a/README.md b/README.md index 6e8f610..3220cf8 100644 --- a/README.md +++ b/README.md @@ -32,43 +32,33 @@ This repo features a custom image based on Raspberry Pi OS Lite built with [pi-g You can build the image yourself and customize the build along the way by following these steps. -1. Setup a Ubuntu VM using [multipass](https://multipass.run/) which will build the image. This provides a clean build environment and additionally works on Linux as well as macOS. +1. Setup a Debian VM using [vagrant](https://www.vagrantup.com/) which will build the image. This provides a clean build environment and additionally works on a Linux as well as macOS. ```bash - multipass launch --name raspios-builder --cpus 8 --mem 16G --disk 25G - multipass transfer install.sh raspios-builder:/home/ubuntu/install.sh - multipass transfer prepare-build.sh raspios-builder:/home/ubuntu/prepare-build.sh + vagrant up ``` -1. Shell into the build VM and prepare the pi-gen build: - ```bash - multipass shell raspios-builder +2. Start pi-gen build in the VM. This is going to take some time... ``` - ```bash - chmod +x prepare-build.sh install.sh - ./install.sh # clone pi-gen and install dependencies - ./prepare-build.sh # add cloud-init build steps + vagrant ssh -c /home/vagrant/pi-cloud-init/build.sh ``` -1. Start pi-gen build in the VM. This is going to take some time... - ``` - cd ~/pi-gen - sudo ./build.sh - ``` - -1. Transfer produced image to the host machine and unzip: +3. Transfer produced image to the host machine and unzip. + This requires the `vagrant-scp` plugin, install it first by running: + ```bash + vagrant plugin install vagrant-scp ``` - vm_zip_file=$(multipass exec raspios-builder -- find /home/ubuntu/pi-gen/deploy -name 'image_*.zip' -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1) - host_zip_file="${vm_zip_file##*/image_}" - multipass transfer raspios-builder:"$vm_zip_file" "$host_zip_file" - unzip -o "$host_zip_file" + ```bash + zip_file=$(date +%Y-%m-%d)-raspios-buster-armhf-lite-cloud-init.zip + vagrant scp raspios-builder:/home/vagrant/pi-cloud-init/$zip_file $zip_file + unzip -o "$zip_file" ``` -1. Customize `user-data.yaml`, `meta-data.yaml` and `network-config.yaml` for the instance you're setting up. +4. Customize `user-data.yaml`, `meta-data.yaml` and `network-config.yaml` for the instance you're setting up. -1. Mount boot partition to inject `user-data`, `meta-data` and `network-config`. +5. Mount boot partition to inject `user-data`, `meta-data` and `network-config`. (It's assuming a macOS machine, but you should be able to accomplish the same using `mount` and `umount` on Linux.) ``` - img_file="${host_zip_file%.zip}.img" + img_file="${zip_file%.zip}.img" volume="$(hdiutil mount "$img_file" | egrep -o '/Volumes/.+')" cp meta-data.yaml "$volume"/meta-data cp user-data.yaml "$volume"/user-data @@ -78,7 +68,7 @@ You can build the image yourself and customize the build along the way by follow diskutil eject "$device" ``` -1. Optionally, you can verify the image and cloud-init functionality using [dockerpi](https://github.com/lukechilds/dockerpi). It start a Docker container with QEMU in it emulating a Pi. This way you can already verify, that the image and the provided `user-data` is working without flashing a new SD card everytime. +6. Optionally, you can verify the image and cloud-init functionality using [dockerpi](https://github.com/lukechilds/dockerpi). It start a Docker container with QEMU in it emulating a Pi. This way you can already verify, that the image and the provided `user-data` is working without flashing a new SD card everytime. ``` docker run -it -v $PWD/$img_file:/sdcard/filesystem.img lukechilds/dockerpi:vm ... @@ -92,9 +82,9 @@ You can build the image yourself and customize the build along the way by follow cloud-init[620]: Cloud-init v. 20.2 finished at Mon, 08 Mar 2021 19:56:08 +0000. Datasource DataSourceNoCloud [seed=/dev/sda1][dsmode=net]. Up 179.17 seconds ``` -1. Now, flash the image including cloud-init data to SD card, using [balena etcher](https://www.balena.io/etcher/), [Raspberry Pi Imager](https://www.raspberrypi.org/software/) or similar. +7. Now, flash the image including cloud-init data to SD card, using [balena etcher](https://www.balena.io/etcher/), [Raspberry Pi Imager](https://www.raspberrypi.org/software/) or similar. -2. Finally, SSH into your Pi and verify cloud-init functionality. By default, the `pi` user is locked and SSH password authentication is disabled, so make sure to use the custom user with `ssh_authorized_keys` from your `user-data`. +8. Finally, SSH into your Pi and verify cloud-init functionality. By default, the `pi` user is locked and SSH password authentication is disabled, so make sure to use the custom user with `ssh_authorized_keys` from your `user-data`. ``` ssh your-user@your-pi cat /var/log/cloud-init-output.log diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..35e0924 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,19 @@ +VM_NAME = "raspios-builder" + +Vagrant.configure("2") do |config| + config.vm.box = "debian/buster64" + + config.vm.define VM_NAME + config.vm.hostname = VM_NAME + + config.vm.provider "virtualbox" do |v| + v.cpus = 8 + v.memory = 16000 + v.name = VM_NAME + end + + config.vm.provision "shell", path: "bootstrap.sh" + + config.vm.synced_folder ".", "/vagrant", disabled: true + config.vm.synced_folder ".", "/home/vagrant/pi-cloud-init", type: "rsync", rsync__auto: true, rsync__exclude: ['*.zip', '*.img'] +end diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..fdf3b29 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,15 @@ +#!/bin/bash -ex + +# workaround for building on 64-bit host (https://github.com/RPi-Distro/pi-gen/issues/271), +# also see https://github.com/RPi-Distro/pi-gen/pull/307 +dpkg --add-architecture i386 + +# Bring system current +apt-get update + +# Install required pi-gen dependencies +apt-get install -y coreutils quilt parted qemu-user-static:i386 debootstrap zerofree zip \ + dosfstools libarchive-tools libcap2-bin grep rsync xz-utils file git curl bc \ + qemu-utils kpartx + +mkdir -p /home/vagrant/pi-cloud-init diff --git a/prepare-build.sh b/build.sh similarity index 79% rename from prepare-build.sh rename to build.sh index 25b1b99..ab50245 100755 --- a/prepare-build.sh +++ b/build.sh @@ -1,7 +1,18 @@ #!/bin/bash -ex -# go to home -cd +# go to home and fetch pi-gen +cd /home/vagrant + +if [ -d pi-gen ] ; then + echo "found pi-gen, skipping clone" +else + echo "cloning pi-gen" + + git clone https://github.com/RPi-Distro/pi-gen.git + pushd pi-gen + chmod +x build.sh + popd +fi pushd pi-gen @@ -39,7 +50,7 @@ EOF ### add cloud-init step to stage2 step="10-cloud-init" if [ -d "$step" ]; then - rm -Rf $step + rm -Rf $step fi mkdir $step && pushd $step @@ -163,3 +174,35 @@ EOF chmod +x 01-run-chroot.sh popd + +### add cgroups step to stage2 +step="11-cgroups" +if [ -d "$step" ]; then + rm -Rf $step +fi +mkdir $step && pushd $step + +cat > 00-run-chroot.sh <<"EOF" +#!/bin/bash + +# Raspberry Pi OS doesn't enable cgroups by default +cmdline_string="cgroup_memory=1 cgroup_enable=memory" + +if ! grep -q "$cmdline_string" /boot/cmdline.txt ; then + sed -i "1 s/\$/ $cmdline_string/" /boot/cmdline.txt +fi +EOF +chmod +x 00-run-chroot.sh + +popd + +# end modifying stage2 +popd + +### start pi-gen build +sudo ./build.sh + +### copy image back to project dir +zip_file=$(find deploy -name 'image_*.zip' -printf '%T@ %p\n' | sort -n | cut -d' ' -f 2- | tail -n 1) +copied_zip_file="${zip_file##*/image_}" +cp "$zip_file" "/home/vagrant/pi-cloud-init/$copied_zip_file" diff --git a/install.sh b/install.sh deleted file mode 100755 index 855aa69..0000000 --- a/install.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -ex - -# go to home -cd - -if [ -d pi-gen ] ; then - echo "found pi-gen, skipping clone" -else - echo "cloning pi-gen" - - git clone https://github.com/RPi-Distro/pi-gen.git - pushd pi-gen - chmod +x build.sh - popd -fi - -# Bring system current -sudo apt-get update - -# Install required pi-gen dependencies -sudo apt-get -y install coreutils quilt parted qemu-user-static debootstrap zerofree zip \ - dosfstools libarchive-tools libcap2-bin grep rsync xz-utils file git curl bc \ - qemu-utils kpartx -