Files
nixos/raspberry/build-snapcast-zero-sd.sh
2024-12-29 22:04:44 +01:00

234 lines
6.4 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# build_rpi_sd_no_chroot_auto.sh
#
# Fully automated Raspberry Pi SD card creation script WITHOUT chroot.
# When the Pi boots the first time, it installs snapclient automatically.
#
# WARNING: This script will format and overwrite $SD_DEVICE!
# Make sure you set $SD_DEVICE correctly.
set -e
#######################################
# CONFIGURATION #
#######################################
# Where to download Raspberry Pi OS Lite if not found
IMG_URL="https://downloads.raspberrypi.org/raspios_lite_armhf_latest"
# The exact .img filename you expect after extraction/unzipping
EXPECTED_IMG="rpi_os_lite_latest.img"
# Adjust to match the real image name. If the official download is .xz or .zip,
# you might need to adapt the script below.
# Your SD card device (e.g., /dev/sdb, /dev/mmcblk0)
SD_DEVICE="/dev/sda"
# Wi-Fi credentials
WIFI_SSID="Cloonar-Multimedia"
WIFI_PASS="K2MC28Zhk\$4zsx6Y"
WIFI_COUNTRY="AT"
# Snapserver IP or hostname
SNAPSERVER_HOST="snapcast.cloonar.com"
#######################################
# FILE NAMES & PATHS ON THE PI #
#######################################
# We'll copy a systemd service and script into the Pi's root filesystem.
FIRSTBOOT_SCRIPT="/usr/local/bin/firstboot.sh"
FIRSTBOOT_SERVICE="/etc/systemd/system/firstboot.service"
#######################################
# DOWNLOAD IMAGE IF NEEDED #
#######################################
download_image_if_needed() {
if [[ ! -f "$EXPECTED_IMG" ]]; then
echo ">>> $EXPECTED_IMG not found, downloading from $IMG_URL..."
wget -O rpi_os_lite_latest.img.xz "$IMG_URL"
echo ">>> Unzipping..."
# unzip rpi_os_lite_latest.zip || true
# If you get a .xz, un-comment:
xz -dv *.xz
if [[ ! -f "$EXPECTED_IMG" ]]; then
echo "ERROR: Expected .img file '$EXPECTED_IMG' not found after extraction!"
exit 1
fi
else
echo ">>> Using existing image file: $EXPECTED_IMG"
fi
}
#######################################
# WRITE IMAGE TO SD #
#######################################
write_image_to_sd() {
echo ">>> Writing $EXPECTED_IMG to $SD_DEVICE..."
umount "${SD_DEVICE}"* || true
dd if="$EXPECTED_IMG" of="$SD_DEVICE" bs=4M conv=fsync status=progress
sync
}
#######################################
# MOUNT BOOT & ROOTFS #
#######################################
mount_partitions() {
if [[ $SD_DEVICE == *"mmcblk"* ]]; then
BOOT_PART="${SD_DEVICE}p1"
ROOT_PART="${SD_DEVICE}p2"
else
BOOT_PART="${SD_DEVICE}1"
ROOT_PART="${SD_DEVICE}2"
fi
mkdir -p /mnt/rpi-boot
mkdir -p /mnt/rpi-root
echo ">>> Mounting boot partition ($BOOT_PART) -> /mnt/rpi-boot"
mount "$BOOT_PART" /mnt/rpi-boot
echo ">>> Mounting root partition ($ROOT_PART) -> /mnt/rpi-root"
mount "$ROOT_PART" /mnt/rpi-root
}
unmount_partitions() {
echo ">>> Unmounting partitions..."
umount /mnt/rpi-boot || true
umount /mnt/rpi-root || true
sync
}
#######################################
# PREPARE BOOT PARTITION (NO CHROOT)
#######################################
enable_ssh_wifi_hifiberry() {
echo ">>> Enabling SSH..."
touch /mnt/rpi-boot/ssh
echo ">>> Creating wpa_supplicant.conf..."
cat << EOF > /mnt/rpi-boot/wpa_supplicant.conf
country=$WIFI_COUNTRY
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="$WIFI_SSID"
psk="$WIFI_PASS"
}
EOF
echo ">>> Enabling HiFiBerry Amp+ overlay in config.txt..."
cat << EOF >> /mnt/rpi-boot/config.txt
# --- HiFiBerry Amp+ overlay ---
dtoverlay=hifiberry-amp
dtparam=audio=off
EOF
}
#######################################
# INSTALL FIRST-BOOT SERVICE/SCRIPT
# (PLACED INTO THE Pi ROOTFS)
#######################################
install_firstboot_autosetup() {
echo ">>> Creating first-boot script ($FIRSTBOOT_SCRIPT) in Pi root filesystem..."
cat << 'FOO' > /mnt/rpi-root$FIRSTBOOT_SCRIPT
#!/usr/bin/env bash
set -e
echo ">>> [FIRST BOOT] Installing snapclient..."
# Update system
apt-get update
apt-get upgrade -y
# Install snapclient
apt-get install -y snapclient
# Configure snapclient
cat << SCLIENT > /etc/default/snapclient
SNAPCLIENT_OPTS="--host SNAPSERVER_PLACEHOLDER"
SCLIENT
systemctl enable snapclient
systemctl start snapclient
echo ">>> [FIRST BOOT] Snapclient installation complete."
# Disable this service so it doesn't run again
systemctl disable firstboot.service
# Optional: remove script & service
rm -f /usr/local/bin/firstboot.sh
rm -f /etc/systemd/system/firstboot.service
FOO
# Replace placeholder with actual snapserver host
sed -i "s|SNAPSERVER_PLACEHOLDER|$SNAPSERVER_HOST|g" /mnt/rpi-root$FIRSTBOOT_SCRIPT
# Make it executable
chmod +x /mnt/rpi-root$FIRSTBOOT_SCRIPT
echo ">>> Creating first-boot systemd service ($FIRSTBOOT_SERVICE)..."
cat << EOF > /mnt/rpi-root$FIRSTBOOT_SERVICE
[Unit]
Description=Run once at first boot to install snapclient
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=$FIRSTBOOT_SCRIPT
RemainAfterExit=true
[Install]
WantedBy=multi-user.target
EOF
echo ">>> Enabling firstboot.service so it runs automatically..."
# We can manually create the symlink to "enable" it:
mkdir -p /mnt/rpi-root/etc/systemd/system/multi-user.target.wants
ln -s $FIRSTBOOT_SERVICE /mnt/rpi-root/etc/systemd/system/multi-user.target.wants/firstboot.service
}
#######################################
# MAIN #
#######################################
main() {
# 1) Download image if needed
download_image_if_needed
# 2) Write image to SD
write_image_to_sd
# 3) Mount partitions
mount_partitions
# 4) Enable SSH, Wi-Fi, HiFiBerry in /boot
enable_ssh_wifi_hifiberry
# 5) Place the "first boot" script & service in / (root partition)
install_firstboot_autosetup
# 6) Unmount
unmount_partitions
echo "=============================================================="
echo "Done! The SD card is fully configured for auto snapclient setup."
echo "Insert it into your Pi, power on, and wait a couple of minutes."
echo ""
echo "What happens on first boot:"
echo " 1. Pi connects to Wi-Fi, SSH is enabled"
echo " 2. 'firstboot.service' runs once, installs snapclient, configures it"
echo " 3. The service disables itself and removes the script"
echo ""
echo "No user intervention is required. Enjoy!"
echo "=============================================================="
}
main "$@"