#!/bin/bash # Collection of setup steps for a new raspberry pi # (e.g. boot from HD, disable swap file, ...) # Get script working directory # (when called from a different directory) WDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >>/dev/null 2>&1 && pwd )" #CONFIG_FILE="$WDIR/${toolName}.cfg" #CONFIG_FILE_DEFAULT="${CONFIG_FILE}.example" osName= distName= RPI_BOOT_CONFIG="/boot/config.txt" seq_config() { # Shift away args local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? # Set download url with specified CPU architecture PIDOWNURL="https://downloads.raspberrypi.org/raspios_lite_${PIARCH}_latest" if [ "$(which lsb_release)" == "" ] ; then warning -e "Cannot detect OS. Assuming Ubuntu" osName="Ubuntu" else osName=$(lsb_release -is) distName=$(lsb_release -cs) fi if [ "$osName" == "" ] ; then warning -e "Error dedecting OS. Assuming Ubuntu" osName="Ubuntu" fi info " Detected OS: $osName $distName" info " Requested CPU Architecture: $PIARCH" return 0 } PIARCH=armhf PIDOWNURL= SDDEV= SDBOOT= SDBOOTPUUID= SDROOT= SDROOTDEV= SDROOTPUUID= HDDEV= HDROOT= HDROOTPUUID= HDSWAP= HDSWAPPUUID= evalArgs() { local argCount=0 for arg in "$@"; do case "$1" in -a|--arch) if [ ! -z "$2" ]; then PIARCH="$2" ((argCount+=2)) else ((argCount+=1)) fi shift $argCount ;; *) break ;; esac done return $argCount } step_1_info() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? echoinfoArgs "[OPTIONS] [SD CARD DEVICE] [HD DEVICE]" echo "Download latest Raspberry Pi OS lite image $PIARCH" if contextExe; then echoinfo "Download URL: $PIDOWNURL" else echoinfo " [OPTIONS]" echoinfo " -a, --arch : armhf (default), arm64" fi } step_1_alias() { echo "setup"; } step_1() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? if [ ! -f "$downLoc" ] ; then exe wget "$PIDOWNURL" -O "$downLoc" echo -ne " [I] sha256 sum of download:\n " exe sha256sum "$downLoc" fi downImgName="${downDir}/$(zipinfo -1 "$downLoc")" if [ ! -f "$downImgName" ] ; then exe unzip "$downLoc" -d "$downDir" endReturn -o $? "Unzip raspios image $PIARCH failed" fi } downImgName="" downDay=$(date +%Y%m%d) downDir="/tmp" downLoc="${downDir}/raspios_$downDay.zip" step_2_info() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? echoinfoArgs "[OPTIONS] [SD CARD DEVICE]" echo "Write Raspberry Pi OS image to SD card" echoinfo "This operation will delete all data previously on the SD card!" contextExe && [ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1" } step_2_alias() { echo "writesd"; } step_2() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? if [ "$downImgName" == "" ] ; then # called again to make sure $downImgName is populated step setup fi if [ ! -f "$downImgName" ] ; then endReturn -o 1 "No raspios image found" fi if [ $(id -u) -ne 0 ] ; then endReturn -o 1 "No root" fi read_sd_dev "$1" # check if device was confirmed if [ $? -ne 0 ] ; then endReturn -o 1 "SD card device not found" fi # write image exe dd bs=8M if="$downImgName" of="$SDDEV" conv=fsync endReturn -o "$?" "Writing image to $SDDEV failed" exe sync # SD partitions will have new informations now # Leave SD card device intact for next step SDBOOT="" SDROOT="" # TODO ? automatic remount warning -e "Please remove SD now and plug it back in." exe read -p " Press enter to contiue." } step_3_info() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? echoinfoArgs "[SD CARD DEVICE]" echo "Prepare SD for first run" if contextExe; then [ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1" fi } step_3() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? if [ -z $1 ] && [ ! -z $SDDEV ] ; then if quiet ; then answer="n" else exe lsblk -p "$SDDEV" echo exe read -p "Is $SDDEV still the SD card (y/[n])? " answer fi case $answer in [yY]) # Nothing todo ;; *) SDDEV="" ;; esac fi read_sd_dev "$1" endReturn -o $? "SD card device not found" if [ ! -w "$SDBOOT" ] ; then error -e "SD card boot partion not writeable" return 1 fi # enable systemd ssh service echo " [I] Enable SSH access" exe touch "$SDBOOT"/ssh # save SD boot settings for easy emergency start from SD echo " [I] Save SD card boot information for later use" exe cp -ar "$SDBOOT"/cmdline.txt "$SDBOOT"/cmdline.txt.sd exe cp -ar "$SDROOT"/etc/fstab "$SDROOT"/etc/fstab.sd } step_4_info() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? echoinfoArgs "[SD CARD DEVICE] [HD DEVICE]" echo "Prepare SD card to boot from hard disk" if contextExe; then [ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1" [ ! -z $2 ] && echoinfo " [HD DEVICE]: $2" fi } step_4_alias() { echo "hdboot"; } step_4() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? read_sd_dev "$1" endReturn -o $? "SD detection error $?" read_hd_dev "$2" endReturn -o $? "HD detection error" echo " [I] SD: $SDDEV" echo " $SDBOOT [$SDBOOTPUUID]" echo " $SDROOT [$SDROOTPUUID]" echo " [I] HD: $HDDEV" echo " $HDROOT [$HDROOTPUUID]" echo " $HDSWAP [$HDSWAPPUUID]" echo # Point boot command line to SSD echo -n " [I] modify PARTUUID of $SDBOOT/cmdline.txt" if [ ! -z $HDROOTPUUID ] ; then exe sed -i -E "s/root=PARTUUID=[a-f0-9-]+/root=PARTUUID=${HDROOTPUUID}/" "$SDBOOT/cmdline.txt" if [ $? -eq 0 ] ; then echo " ... Ok" else echo -e "\n Failed! Replace PARTUUID manually" fi else echo " Replace \"root=PARTUUID=******00-01\" manually" fi # Disable initial resizing of the second partition echo -n " [I] remove \"init=/usr/lib/raspi-config/init_resize.sh\"" exe sed -i -E "s/[ ]*init=.*\/init_resize\.sh//" "$SDBOOT/cmdline.txt" if [ $? -eq 0 ] ; then echo " ... Ok" else echo -e "\n Failed! Remove init=... manually" fi # Save modifications for HD boot exe cp -ar "$SDBOOT"/cmdline.txt "$SDBOOT"/cmdline.txt.hd echo # Resize second partition of SD to max. possible size echo " [I] Resize root partion of SD: ${SDROOT} " step resizesd "$SDDEV" if [ $? -ne 0 ] ; then warning -e "Something seems to have failed during resize" else # Disable init script to resize SD echo -n " [I] remove \"init=\" part from $SDBOOT/cmdline.txt.sd" exe sed -i -E "s/[ ]*init=.*\/init_resize\.sh//" "$SDBOOT/cmdline.txt.sd" if [ $? -eq 0 ] ; then echo " ... Ok" else echo -e "\n Failed! Remove init=... manually" fi fi } step_5_info() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? echoinfoArgs "[SD CARD DEVICE] [HD DEVICE]" echo "Prepare HD for boot (TODO)" if contextExe; then [ ! -z $1 ] && echoinfo " [SD CARD DEVICE]: $1" [ ! -z $2 ] && echoinfo " [HD DEVICE]: $2" fi } step_5() { # Shift away args shift; local lArgs=( "$@" ); evalArgs "${lArgs[@]}"; shift $? #TODO error -e "Not ready yet...TODO" #return 1 read_sd_dev "$1" endReturn -o $? "SD detection error $?" read_hd_dev "$2" endReturn -o $? "HD detection error" echo " [I] SD: $SDDEV" echo " $SDBOOT [$SDBOOTPUUID]" echo " $SDROOT [$SDROOTPUUID]" echo " [I] HD: $HDDEV" echo " $HDROOT [$HDROOTPUUID]" echo " $HDSWAP [$HDSWAPPUUID]" echo # TODO how to partition HD echo " [I] $HDDEV is expected to be partitioned with root and swap" echo " TODO create a step for partitioning script support?!" echo # Initial rsync of system to HD echo " [I] Clone SD root to HD root:" echo " rsync -avxHAX --numeric-ids --info=stats2 $SDROOT/ $HDROOT/" echo # Modify fstab on HD for root and swap on HD echo " [I] modify $HDROOT/etc/fstab" echo " PARTUUID=$SDBOOTPUUID /boot vfat ro,defaults 0 2" echo " PARTUUID=$SDROOTPUUID /backup ext4 ro,defaults,noatime 0 2" echo " PARTUUID=$HDROOTPUUID / ext4 defaults,noatime 0 1" echo " PARTUUID=$HDSWAPPUUID none swap sw 0 0" echo # etc echo " [I] modify $HDROOT/etc/dhcpcd.conf for static IPs" } read_sd_dev() { local partExt="" if [ ! -z "$1" ] ; then SDBOOT= SDROOT= SDROOTDEV= SDROOTPUUID= SDBOOTPUUID= SDDEV="$1" elif [ -z $SDDEV ] || [ ! -b "$SDDEV" ] ; then SDDEV= SDBOOT= SDROOT= SDROOTDEV= SDBOOTPUUID= SDROOTPUUID= echo " [I] Available devices:" echo exe lsblk -p echo exe read -p "Provide SD card device (e.g. /dev/sdb): " SDDEV fi if [ ! -b "$SDDEV" ] ; then info -e "$SDDEV not a block device" SDDEV= return 1 fi if [[ "$SDDEV" =~ .*blk.* ]] ; then partExt="p" fi if [ -z $SDBOOT ] ; then SDBOOT=$(findmnt -no TARGET "${SDDEV}${partExt}${SDBOOTPARTNO}") fi if [ -z $SDBOOTPUUID ] ; then IFS=\" read -r _ vPARTUUID _ < <(blkid "${SDDEV}${partExt}${SDBOOTPARTNO}" -s PARTUUID) SDBOOTPUUID=$vPARTUUID fi SDROOTDEV=${SDDEV}${partExt}${SDROOTPARTNO} if [ -z $SDROOT ] ; then SDROOT=$(findmnt -no TARGET "${SDROOTDEV}") fi if [ -z $SDROOTPUUID ] ; then SDROOTPUUID=$(findmnt -no PARTUUID "${SDROOTDEV}") fi return 0 } SDBOOTPARTNO=1 SDROOTPARTNO=2 read_hd_dev() { if [ ! -z "$1" ] ; then HDROOT= HDROOTPUUID= HDSWAPPUUID= HDDEV="$1" elif [ -z $HDDEV ] || [ ! -b "$HDDEV" ] ; then HDROOT= HDROOTPUUID= HDSWAPPUUID= echo " [I] Available devices:" echo exe lsblk -p echo exe read -p "Provide HD device (e.g. /dev/sdf): " HDDEV fi if [ ! -b "$HDDEV" ] ; then HDDEV= return 1 fi if [ -z $HDROOT ] ; then HDROOT=$(findmnt -no TARGET "${HDDEV}1") fi if [ -z $HDROOTPUUID ] ; then IFS=\" read -r _ vPARTUUID _ < <(blkid "${HDDEV}1" -s PARTUUID) HDROOTPUUID=$vPARTUUID fi if [ -z $HDSWAPPUUID ] ; then IFS=\" read -r _ vPARTUUID _ < <(blkid "${HDDEV}2" -s PARTUUID) HDSWAPPUUID=$vPARTUUID HDSWAP="${HDDEV}2" fi return 0 } step_20_info() { echo "Disable swap file and remove it"; } step_20_alias() { echo "disable_swap"; } step_20() { exe swapoff -a exe systemctl disable dphys-swapfile exe rm -rf "$rpiSwapFile" warning -e "Reboot to apply changes" if interactive ; then exe read -p " Reboot now ([n]/y)? " answer case $answer in [yY]) info -e "Rebooting now ..." exe reboot ;; *) ;; esac fi } rpiSwapFile="/var/swap" step_22_info() { echoinfoArgs "[SD CARD DEVICE]"; echo "Resize second SD card partition"; } step_22_alias() { echo "resizesd"; } step_22() { shift read_sd_dev "$1" if [ -z $SDDEV ] || [ "$SDDEV" = "" ] || [ "$SDROOT" == "/" ] ; then error -e "No SD found" return 1 fi echo " [I] Device to be resized: $SDROOTDEV" exe umount -q "$SDROOT" exe parted -s "$SDDEV" "resizepart $SDROOTPARTNO -1" quit saveReturn $? exe e2fsck -f "$SDROOTDEV" saveReturn $? exe resize2fs "$SDROOTDEV" saveReturn $? if [ -z $SDROOT ] ; then read -p "Please provide a mountpoint: " SDROOT exe mkdir -p "$SDROOT" fi exe mount "$SDROOTDEV" "$SDROOT" saveReturn $? getReturn return $? } step_24_info() { echoinfoArgs "[OPTION]" echo "Turn off power LED" echoinfo " [OPTION]" echoinfo " -p : Turn off permanentely (/etc/rc.local)" } step_24_alias() { echo "disable_powerled"; } step_24() { exep "${ledOffCmd}" if [ ! -z "$2" ] && [ "$2" == "-p" ] ; then exep "grep \"$ledPowerBright\" $startScript >>/dev/null" if [ $? -eq 0 ] ; then echo " [I] Power LED brightness already used. Please check $startScript manually for:" echo " $ledOffCmd" return 1 fi exe sed -i "s/^exit 0/# Turn off power LED/" "$startScript" exep "echo \"${ledOffCmd}\" >> $startScript" exep "echo -e \"\nexit 0\" >> $startScript" fi } startScript="/etc/rc.local" ledPowerBright="/sys/class/leds/led1/brightness" ledOffCmd="sudo sh -c 'echo 0 > ${ledPowerBright}'" step_26_info() { echo "Restart network without reboot"; } step_26_alias() { echo "netrestart"; } step_26() { exep "sudo ip link set eth0 down && sudo ip link set eth0 up" } step_28_info() { echo "Disable bluetooth"; } step_28_alias() { echo "disable_bluetooth"; } step_28() { checkBootConfig "$RPI_CONFIG_DTOVERLAY" "$RPI_CONF_DI_BLUETOOTH" [ $? -eq 0 ] && endReturn -o 1 "Bluetooth already disabled" addConf -a "${RPI_CONFIG_DTOVERLAY}=$RPI_CONF_DI_BLUETOOTH" "$RPI_BOOT_CONFIG" } RPI_CONFIG_DTOVERLAY="dtoverlay" RPI_CONF_DI_BLUETOOTH="disable-bt" RPI_CONF_DI_WIFI="disable-wifi" step_29_info() { echo "Disable bluetooth services"; } step_29() { exe systemctl disable hciuart.service exe systemctl disable bluealsa.service exe systemctl disable bluetooth.service info "Consider uninstalling bluetooth software:" info "apt purge --autoremove -y bluez" info warning "Reboot to make changes active" } step_31_info() { echo "Disable Wifi"; } step_31_alias() { echo "disable_wifi"; } step_31() { checkBootConfig "$RPI_CONFIG_DTOVERLAY" "$RPI_CONF_DI_WIFI" [ $? -eq 0 ] && endReturn -o 1 "Wifi already disabled" addConf -a "${RPI_CONFIG_DTOVERLAY}=$RPI_CONF_DI_WIFI" "$RPI_BOOT_CONFIG" warning "Reboot to make changes active" } step_33_info() { echo "Disable HDMI"; } step_33_alias() { echo "disable_hdmi"; } step_33() { checkBootConfig "$RPI_CONFIG_HDMI_BLANK" "$RPI_CONF_DI_HDMI" [ $? -eq 0 ] && endReturn -o 1 "HDMI already disabled" addConf -a "${RPI_CONFIG_HDMI_BLANK}=$RPI_CONF_DI_HDMI" "$RPI_BOOT_CONFIG" } RPI_CONFIG_HDMI_BLANK="hdmi_blanking" RPI_CONF_DI_HDMI="1" step_34_info() { echo "Disable TV service"; } step_34() { exe $tvserviceOffCmd exep "grep \"$tvserviceBin\" $startScript >>/dev/null" if [ $? -eq 0 ] ; then echo " [I] Tvservice already used. Please check $startScript manually for:" echo " $tvserviceOffCmd" return 1 fi exe sed -i "s/^exit 0/# Turn off tvservice/" "$startScript" exep "echo \"${tvserviceOffCmd}\" >> $startScript" exep "echo -e \"\nexit 0\" >> $startScript" warning "Reboot to make changes active" } tvserviceBin="/usr/bin/tvservice" tvserviceOffCmd="${tvserviceBin} -o'" # checkBootConfig [VALUE] checkBootConfig() { [ -z "$1" ] && return 1 local re_check="^[[:blank:]]*[^#]*${1}[[:blank:]]*=[[:blank:]]*$2" grep -rqE "$re_check" "$RPI_BOOT_CONFIG" return $? } step_100_alias() { echo "notes"; } step_100() { color green cat < System Options)) * Configure Timezone (\`raspi-confg\` -> Localisation Options) * Set GPU memory (\`raspi-config\` -> Performance Options) * Configure swap partition [/etc/fstab] > \`PARTUUID=******-03 none swap sw 0 0\` \`$SEQ_NAME disable_swap\` * Update system \`apt update && apt dist-upgrade\` * Configure own NTP server [/etc/systemd/timesyncd.conf] > NTP= \`system systemd-timesyncd restart\` * Configure vim to remember last position in a file Uncomment the following in [/etc/vim/vimrc] > \`au BufReadPost ...\` NOTES_EOF } readonly sqr_minVersion=16 . /usr/local/bin/sequencer.sh