Image script: trixie arm64, NetworkManager wifi, any free loop device
- Download the 2026-09-15 Raspberry Pi OS trixie arm64 lite image. - Trixie (and NetworkManager-based bookworm) ignore wpa_supplicant.conf on the boot partition: write a NetworkManager profile there instead, and set the regulatory domain on the kernel command line. The SSID is now asked for too. - Use whichever loop device is free rather than a hard-coded /dev/loop42, mount into a temporary directory, and unmount and detach on any exit. Resolve paths from the script's own location, and refuse to overwrite an already customised image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
set -e # exit on error
|
set -e # exit on error
|
||||||
|
|
||||||
TARGET_FOLDER="./rpi_image"
|
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
||||||
IMG_FILE_BASENAME="2023-12-11-raspios-bookworm-armhf-lite"
|
TARGET_FOLDER="$SCRIPT_DIR/rpi_image"
|
||||||
#DOWNLOAD_URL="https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-11-08/${IMG_FILE_BASENAME}.zip"
|
#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"
|
#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"
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n Hostname of new pi
|
|
||||||
read -p "Hostname of new pi [newrpi]: " RPI_HOSTNAME
|
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
|
read -p "WIFI password (leave empty for non-wifi setup) [] " WIFI_PASSWORD
|
||||||
RPI_HOSTNAME=${RPI_HOSTNAME:-newrpi}
|
RPI_HOSTNAME=${RPI_HOSTNAME:-newrpi}
|
||||||
|
WIFI_SSID=${WIFI_SSID:-WLAN}
|
||||||
|
|
||||||
SCRIPT_DIR=`pwd`
|
mkdir -p "$TARGET_FOLDER"
|
||||||
mkdir -p $TARGET_FOLDER
|
cd "$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"
|
echo "Downloading image"
|
||||||
wget ${DOWNLOAD_URL}
|
wget ${DOWNLOAD_URL}
|
||||||
@@ -36,36 +43,74 @@ unxz ${IMG_FILE_BASENAME}.img.xz
|
|||||||
|
|
||||||
|
|
||||||
echo "Mounting image"
|
echo "Mounting image"
|
||||||
mkdir mounted_image
|
MOUNT_DIR=$(mktemp -d "$TARGET_FOLDER/mounted_image.XXXXXX")
|
||||||
mkdir mounted_image/boot
|
LOOP_DEV=""
|
||||||
mkdir mounted_image/system
|
cleanup() {
|
||||||
losetup -P /dev/loop42 ${IMG_FILE_BASENAME}.img
|
set +e
|
||||||
mount /dev/loop42p1 mounted_image/boot
|
umount "$MOUNT_DIR/boot" "$MOUNT_DIR/system" 2>/dev/null
|
||||||
mount /dev/loop42p2 mounted_image/system
|
[ -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 "Enabling SSH and writing hostname"
|
||||||
echo $RPI_HOSTNAME > mounted_image/system/etc/hostname
|
echo $RPI_HOSTNAME > "$MOUNT_DIR/system/etc/hostname"
|
||||||
touch mounted_image/boot/ssh # startup ssh
|
touch "$MOUNT_DIR/boot/ssh" # startup ssh
|
||||||
sed -i "/^#PermitRootLogin/ cPermitRootLogin prohibit-password" mounted_image/system/etc/ssh/sshd_config
|
sed -i "/^#PermitRootLogin/ cPermitRootLogin prohibit-password" "$MOUNT_DIR/system/etc/ssh/sshd_config"
|
||||||
mkdir -p mounted_image/system/root/.ssh
|
mkdir -p "$MOUNT_DIR/system/root/.ssh"
|
||||||
cat $SCRIPT_DIR/*.pub > mounted_image/system/root/.ssh/authorized_keys
|
cat $SCRIPT_DIR/*.pub > "$MOUNT_DIR/system/root/.ssh/authorized_keys"
|
||||||
chmod 700 mounted_image/system/root/.ssh
|
chmod 700 "$MOUNT_DIR/system/root/.ssh"
|
||||||
chmod 600 mounted_image/system/root/.ssh/authorized_keys
|
chmod 600 "$MOUNT_DIR/system/root/.ssh/authorized_keys"
|
||||||
|
|
||||||
|
|
||||||
if [ -z "$WIFI_PASSWORD" ]
|
if [ -z "$WIFI_PASSWORD" ]
|
||||||
then
|
then
|
||||||
echo "Skipping WIFI setup"
|
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 <<EOM >"$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
|
else
|
||||||
echo "Setting up initial wifi config"
|
echo "Setting up initial wifi config (wpa_supplicant)"
|
||||||
/bin/cat <<EOM >mounted_image/boot/wpa_supplicant.conf
|
/bin/cat <<EOM >"$MOUNT_DIR/boot/wpa_supplicant.conf"
|
||||||
country=DE
|
country=DE
|
||||||
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
|
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
|
||||||
update_config=1
|
update_config=1
|
||||||
|
|
||||||
network={
|
network={
|
||||||
ssid="WLAN"
|
ssid="${WIFI_SSID}"
|
||||||
psk="${WIFI_PASSWORD}"
|
psk="${WIFI_PASSWORD}"
|
||||||
}
|
}
|
||||||
EOM
|
EOM
|
||||||
@@ -75,12 +120,8 @@ fi
|
|||||||
|
|
||||||
echo "Unmounting image and other cleanup"
|
echo "Unmounting image and other cleanup"
|
||||||
sleep 3 # to prevent "device is busy"
|
sleep 3 # to prevent "device is busy"
|
||||||
umount /dev/loop42p1
|
cleanup
|
||||||
umount /dev/loop42p2
|
trap - EXIT
|
||||||
losetup -d /dev/loop42
|
|
||||||
rmdir mounted_image/boot
|
|
||||||
rmdir mounted_image/system
|
|
||||||
rmdir mounted_image
|
|
||||||
rm ${IMG_FILE_BASENAME}.img.xz.sha256
|
rm ${IMG_FILE_BASENAME}.img.xz.sha256
|
||||||
chmod a+rw ${IMG_FILE_BASENAME}.img .
|
chmod a+rw ${IMG_FILE_BASENAME}.img .
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user