Files
reterminal-dm4/emmc-provisioning/scripts/edit-cloudinit-on-image.sh
nearxos c5e418eabc Update provisioning documentation and scripts for improved Proxmox deployment</message>
<message>Add a new step-by-step guide for deploying the CM4 eMMC provisioning service on a new Proxmox instance, enhancing clarity for users. Update existing documentation to reflect changes in network configuration options, including the introduction of LAN subnet settings for DHCP and TFTP. Modify cloud-init scripts to ensure proper management of DNS settings and improve the handling of network interfaces. Additionally, enhance the toggle script for network boot to dynamically read the LAN gateway from configuration files, streamlining the setup process and improving user experience.
2026-03-03 08:24:18 +02:00

131 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Mount a Raspberry Pi OS .img or .img.xz, edit cloud-init NoCloud files on the boot
# partition, then unmount and (if .img.xz) recompress. Requires sudo for loop/mount.
#
# Usage:
# ./edit-cloudinit-on-image.sh <path-to-image.img.xz>
# ./edit-cloudinit-on-image.sh <path-to-image.img>
#
# Options:
# --no-recompress If image was .img.xz, leave decompressed .img and do not overwrite
# --replace-with-repo Copy user-data, meta-data, network-config from repo before editing
#
# Example:
# ./edit-cloudinit-on-image.sh /path/to/gnss-bootstrap-20260223-215010.img.xz
#
# Backup the image before running if you want to keep the original.
set -e
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
CLOUDINIT_SRC="$REPO_ROOT/emmc-provisioning/cloud-init"
NO_RECOMPRESS=""
REPLACE_WITH_REPO=""
while [[ $# -gt 0 ]]; do
case "$1" in
--no-recompress) NO_RECOMPRESS=1; shift ;;
--replace-with-repo) REPLACE_WITH_REPO=1; shift ;;
-*) echo "Unknown option: $1"; exit 1 ;;
*) break ;;
esac
done
IMAGE_IN="$1"
[[ -n "$IMAGE_IN" && -f "$IMAGE_IN" ]] || {
echo "Usage: $0 [--no-recompress] [--replace-with-repo] <path-to-image.img.xz|.img>"
echo "Example: $0 gnss-bootstrap-20260223-215010.img.xz"
exit 1
}
IMAGE_IN="$(realpath "$IMAGE_IN")"
WORK_DIR=""
IMG_FILE=""
ORIGINAL_XZ=""
cleanup() {
if [[ -n "$MNT" && -d "$MNT" ]]; then
sudo umount "$MNT" 2>/dev/null || true
fi
if [[ -n "$LOOP" && -b "$LOOP" ]]; then
sudo losetup -d "$LOOP" 2>/dev/null || true
fi
if [[ -n "$WORK_DIR" && -d "$WORK_DIR" ]]; then
if [[ -n "$NO_RECOMPRESS" && -n "$ORIGINAL_XZ" ]]; then
echo "Work dir left at: $WORK_DIR"
else
rm -rf "$WORK_DIR"
fi
fi
}
trap cleanup EXIT
if [[ "$IMAGE_IN" == *.img.xz ]]; then
ORIGINAL_XZ="$IMAGE_IN"
echo "Decompressing $(basename "$ORIGINAL_XZ") (this may take a minute and needs ~3GB free)…"
WORK_DIR=$(mktemp -d -p "${TMPDIR:-/tmp}" edit-cloudinit.XXXXXX)
IMG_FILE="$WORK_DIR/image.img"
xz -T 0 -d -k -f -c "$ORIGINAL_XZ" > "$IMG_FILE"
else
WORK_DIR=$(mktemp -d -p "${TMPDIR:-/tmp}" edit-cloudinit.XXXXXX)
IMG_FILE="$IMAGE_IN"
fi
echo "Attaching image and mounting boot partition…"
LOOP=$(sudo losetup -f --show -P "$IMG_FILE")
# Force kernel to scan partition table so /dev/loopNp1, p2 etc. appear
sudo partprobe "$LOOP" 2>/dev/null || true
sleep 0.5
boot_part="${LOOP}p1"
[[ -b "$boot_part" ]] || boot_part="${LOOP}p2"
[[ -b "$boot_part" ]] || {
echo "Boot partition not found on image. Partitions on image:"
ls -la "${LOOP}"p* 2>/dev/null || true
sudo fdisk -l "$IMG_FILE" 2>/dev/null || true
exit 1
}
MNT="$WORK_DIR/mnt"
mkdir -p "$MNT"
sudo mount "$boot_part" "$MNT"
if [[ -n "$REPLACE_WITH_REPO" && -d "$CLOUDINIT_SRC" ]]; then
echo "Copying cloud-init files from repo into boot partition…"
for f in user-data meta-data network-config; do
if [[ -f "$CLOUDINIT_SRC/$f" ]]; then
sudo cp "$CLOUDINIT_SRC/$f" "$MNT/$f"
elif [[ -f "$CLOUDINIT_SRC/$f.bootstrap" ]]; then
sudo cp "$CLOUDINIT_SRC/$f.bootstrap" "$MNT/$f"
fi
done
fi
echo ""
echo "Boot partition is mounted at: $MNT"
echo "Cloud-init files to edit:"
echo " $MNT/user-data"
echo " $MNT/meta-data"
echo " $MNT/network-config"
echo ""
EDITOR="${EDITOR:-nano}"
echo "Opening editor ($EDITOR). Save and exit when done."
read -r -p "Press Enter to open $EDITOR on these files…"
sudo "$EDITOR" "$MNT/user-data" "$MNT/meta-data" "$MNT/network-config"
echo "Unmounting…"
sudo umount "$MNT"
MNT=""
sudo losetup -d "$LOOP"
LOOP=""
if [[ -n "$ORIGINAL_XZ" && -z "$NO_RECOMPRESS" ]]; then
echo "Recompressing to $(basename "$ORIGINAL_XZ")"
xz -T 0 -z -f -k "$IMG_FILE"
mv -f "${IMG_FILE}.xz" "$ORIGINAL_XZ"
echo "Done. Updated: $ORIGINAL_XZ"
rm -rf "$WORK_DIR"
WORK_DIR=""
elif [[ -n "$NO_RECOMPRESS" && -n "$ORIGINAL_XZ" ]]; then
echo "Left decompressed image at: $IMG_FILE"
echo "Recompress manually: xz -z -k \"$IMG_FILE\""
fi