diff --git a/scripts/create-raspian-image/create-raspian-image.sh b/scripts/create-raspian-image/create-raspian-image.sh index e3cfaaf..64b4178 100755 --- a/scripts/create-raspian-image/create-raspian-image.sh +++ b/scripts/create-raspian-image/create-raspian-image.sh @@ -2,10 +2,12 @@ set -e # exit on error -TARGET_FOLDER="./rpi_image" -IMG_FILE_BASENAME="2023-12-11-raspios-bookworm-armhf-lite" -#DOWNLOAD_URL="https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-11-08/${IMG_FILE_BASENAME}.zip" -DOWNLOAD_URL="https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2023-12-11/${IMG_FILE_BASENAME}.img.xz" +SCRIPT_DIR=$(dirname "$(readlink -f "$0")") +TARGET_FOLDER="$SCRIPT_DIR/rpi_image" +#IMG_FILE_BASENAME="2023-12-11-raspios-bookworm-armhf-lite" +#DOWNLOAD_URL="https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2023-12-11/${IMG_FILE_BASENAME}.img.xz" +IMG_FILE_BASENAME="2026-09-15-raspios-trixie-arm64-lite" +DOWNLOAD_URL="https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2026-09-15/${IMG_FILE_BASENAME}.img.xz" echo "This script downloads raspian lite, and modifies the image to enable SSH and set hostname" @@ -14,15 +16,20 @@ if [[ $EUID -ne 0 ]]; then exit 1 fi -echo -n Hostname of new pi read -p "Hostname of new pi [newrpi]: " RPI_HOSTNAME +read -p "WIFI SSID (only used if a password is given) [WLAN]: " WIFI_SSID read -p "WIFI password (leave empty for non-wifi setup) [] " WIFI_PASSWORD RPI_HOSTNAME=${RPI_HOSTNAME:-newrpi} +WIFI_SSID=${WIFI_SSID:-WLAN} -SCRIPT_DIR=`pwd` -mkdir -p $TARGET_FOLDER -cd $TARGET_FOLDER +mkdir -p "$TARGET_FOLDER" +cd "$TARGET_FOLDER" +if [ -e "${IMG_FILE_BASENAME}.img" ]; then + echo "${TARGET_FOLDER}/${IMG_FILE_BASENAME}.img already exists (already customised?)." + echo "Remove it first if you want to start over." + exit 1 +fi echo "Downloading image" wget ${DOWNLOAD_URL} @@ -36,36 +43,74 @@ unxz ${IMG_FILE_BASENAME}.img.xz echo "Mounting image" -mkdir mounted_image -mkdir mounted_image/boot -mkdir mounted_image/system -losetup -P /dev/loop42 ${IMG_FILE_BASENAME}.img -mount /dev/loop42p1 mounted_image/boot -mount /dev/loop42p2 mounted_image/system +MOUNT_DIR=$(mktemp -d "$TARGET_FOLDER/mounted_image.XXXXXX") +LOOP_DEV="" +cleanup() { + set +e + umount "$MOUNT_DIR/boot" "$MOUNT_DIR/system" 2>/dev/null + [ -n "$LOOP_DEV" ] && losetup -d "$LOOP_DEV" + rmdir "$MOUNT_DIR/boot" "$MOUNT_DIR/system" "$MOUNT_DIR" 2>/dev/null +} +trap cleanup EXIT + +mkdir "$MOUNT_DIR/boot" "$MOUNT_DIR/system" +LOOP_DEV=$(losetup -f --show -P ${IMG_FILE_BASENAME}.img) +mount ${LOOP_DEV}p1 "$MOUNT_DIR/boot" # firmware partition, /boot/firmware on the Pi +mount ${LOOP_DEV}p2 "$MOUNT_DIR/system" echo "Enabling SSH and writing hostname" -echo $RPI_HOSTNAME > mounted_image/system/etc/hostname -touch mounted_image/boot/ssh # startup ssh -sed -i "/^#PermitRootLogin/ cPermitRootLogin prohibit-password" mounted_image/system/etc/ssh/sshd_config -mkdir -p mounted_image/system/root/.ssh -cat $SCRIPT_DIR/*.pub > mounted_image/system/root/.ssh/authorized_keys -chmod 700 mounted_image/system/root/.ssh -chmod 600 mounted_image/system/root/.ssh/authorized_keys +echo $RPI_HOSTNAME > "$MOUNT_DIR/system/etc/hostname" +touch "$MOUNT_DIR/boot/ssh" # startup ssh +sed -i "/^#PermitRootLogin/ cPermitRootLogin prohibit-password" "$MOUNT_DIR/system/etc/ssh/sshd_config" +mkdir -p "$MOUNT_DIR/system/root/.ssh" +cat $SCRIPT_DIR/*.pub > "$MOUNT_DIR/system/root/.ssh/authorized_keys" +chmod 700 "$MOUNT_DIR/system/root/.ssh" +chmod 600 "$MOUNT_DIR/system/root/.ssh/authorized_keys" if [ -z "$WIFI_PASSWORD" ] then echo "Skipping WIFI setup" +elif [ -d "$MOUNT_DIR/system/etc/NetworkManager" ] && [ -e "$MOUNT_DIR/boot/user-data" ] +then + # Trixie (and bookworm images from 2023-10 on, when they use NetworkManager) ignore + # wpa_supplicant.conf on the boot partition; give NetworkManager a connection profile. + echo "Setting up initial wifi config (NetworkManager)" + NM_DIR="$MOUNT_DIR/system/etc/NetworkManager/system-connections" + mkdir -p "$NM_DIR" + /bin/cat <"$NM_DIR/wifi.nmconnection" +[connection] +id=wifi +type=wifi +autoconnect=true + +[wifi] +mode=infrastructure +ssid=${WIFI_SSID} + +[wifi-security] +key-mgmt=wpa-psk +psk=${WIFI_PASSWORD} + +[ipv4] +method=auto + +[ipv6] +method=auto +EOM + chmod 600 "$NM_DIR/wifi.nmconnection" # NetworkManager ignores profiles readable by others + # regulatory domain, so the 5GHz channels and the right power limits are usable at boot + sed -i '1 s/$/ cfg80211.ieee80211_regdom=DE/' "$MOUNT_DIR/boot/cmdline.txt" else - echo "Setting up initial wifi config" - /bin/cat <mounted_image/boot/wpa_supplicant.conf + echo "Setting up initial wifi config (wpa_supplicant)" + /bin/cat <"$MOUNT_DIR/boot/wpa_supplicant.conf" country=DE ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ - ssid="WLAN" + ssid="${WIFI_SSID}" psk="${WIFI_PASSWORD}" } EOM @@ -75,12 +120,8 @@ fi echo "Unmounting image and other cleanup" sleep 3 # to prevent "device is busy" -umount /dev/loop42p1 -umount /dev/loop42p2 -losetup -d /dev/loop42 -rmdir mounted_image/boot -rmdir mounted_image/system -rmdir mounted_image +cleanup +trap - EXIT rm ${IMG_FILE_BASENAME}.img.xz.sha256 chmod a+rw ${IMG_FILE_BASENAME}.img .