From ad47f737312e70662567e068215a636914b56c9d Mon Sep 17 00:00:00 2001 From: macmpi <16296055+macmpi@users.noreply.github.com> Date: Mon, 20 Nov 2023 09:00:41 +0100 Subject: [PATCH] version 1.2 New feature: auto-update apkovl file with latest master gadget: improved setup if several ports available wlan: only start wpa_supplicant if needed updated doc --- README.md | 15 +-- headless.apkovl.tar.gz | Bin 7547 -> 8555 bytes headless.apkovl.tar.gz.sha512 | 1 + make.sh | 3 +- overlay/usr/local/bin/headless_bootstrap | 123 ++++++++++++++++------- sample_auto-updt | 10 ++ sample_unattended.sh | 7 +- 7 files changed, 114 insertions(+), 45 deletions(-) create mode 100644 headless.apkovl.tar.gz.sha512 create mode 100644 sample_auto-updt diff --git a/README.md b/README.md index 8427b02..3a5dfb6 100644 --- a/README.md +++ b/README.md @@ -25,15 +25,18 @@ Extra files may be added next to `headless.apkovl.tar.gz` to customise boostrapp - `interfaces`[^3] (*optional*): define network interfaces at will, if defaults DCHP-based are not suitable. - `authorized_keys` (*optional*): provide client's public SSH key to secure `root` ssh login. - `ssh_host_*_key*` (*optional*): provide server's custom ssh keys to be injected (may be stored), instead of using bundled ones[^2] (not stored). Providing an empty key file will trigger new keys generation (ssh server may take longer to start). - - -**Goody:** seamless USB-serial & USB-ethernet gadget mode (PiZero for instance):\ -On supporting Pi devices, just add `dtoverlay=dwc2,dr_mode=peripheral` in `usercfg.txt` (or `config.txt`), and plug USB cable into host Computer port.\ -Serial terminal can then be connected-to from host Computer (e.g. `cu -l ttyACM0` on Linux. xon/xoff flow control).\ -Alternatively, with host Computer set-up to share networking with USB interface as 10.42.0.1 gateway, one can log into device from host with: `ssh root@10.42.0.2`. +- `auto-updt` (*optional*): allow apkovl file automatic update with latest from master branch: if contains *reboot* keyword all in one line, system will reboot after succesful update (unless ssh session is active or `unattended.sh` script is available). Main execution steps are logged: `cat /var/log/messages | grep headless`. +## Goody: +Seamless USB-serial & USB-ethernet gadget mode (*e.g. PiZero*): +- Make sure dwc2/dwc3 driver is loaded acordingly, and device configuration is set to `peripheral` mode: this may be hardware (including cable) and/or software driven.\ +(on supporting Pi devices, just add `dtoverlay=dwc2,dr_mode=peripheral` in `usercfg.txt` (or `config.txt`) to force by software) +- Plug USB cable into host Computer port before boot.\ +Serial terminal can then be connected-to from host Computer (e.g. `cu -l ttyACM0` on Linux. xon/xoff flow control).\ +Alternatively, with host Computer set-up to share networking with USB interface as 10.42.0.1 gateway, one can log into device from host with: `ssh root@10.42.0.2`. + [^1]: Initial boot fully preserves system's original state (config files & installed packages): a fresh system will therefore come-up as unconfigured. [^2]: About bundled ssh keys: this overlay is meant to **quickly bootstrap** system in order to then proceed with proper install; therefore it purposely embeds [some ssh keys](https://github.com/macmpi/alpine-linux-headless-bootstrap/tree/main/overlay/tmp/.trash) so that bootstrapping is as fast as possible. Those temporary keys are moved in RAM /tmp: they will **not be stored/reused** once actual system install is performed (whether or not ssh server is installed in final setup). diff --git a/headless.apkovl.tar.gz b/headless.apkovl.tar.gz index 8a57b83d8c4d9a00aef5eeab6b579d268fb77a0a..e7dcbe170e485dcfeb2fb90d1f5ca15ebc8146ed 100644 GIT binary patch delta 6586 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 Q&;RrDKa?qOssMNZ0Ax5humAu6 diff --git a/headless.apkovl.tar.gz.sha512 b/headless.apkovl.tar.gz.sha512 new file mode 100644 index 0000000..df6b8d6 --- /dev/null +++ b/headless.apkovl.tar.gz.sha512 @@ -0,0 +1 @@ +2dde95eb40fd626a7908ac33f41d47dbd46b0029d110ae8daaaed3575d1ada20e0b4f0268c040311159375b11eac48ce812c8f66993cb5e47c3078a6eb95a7b8 headless.apkovl.tar.gz diff --git a/make.sh b/make.sh index ca10909..0297fb7 100755 --- a/make.sh +++ b/make.sh @@ -30,7 +30,8 @@ if [ -n "$build_path" ]; then doas tar cv -C "$build_path"/overlay --no-recursion \ $(doas find "$build_path"/overlay/ | sed "s|$build_path/overlay/||" | sort | xargs ) | \ gzip -c9n > headless.apkovl.tar.gz - TZ=UTC touch -cm -t "$t_stamp" headless.apkovl.tar.gz + sha512sum headless.apkovl.tar.gz > headless.apkovl.tar.gz.sha512 + TZ=UTC touch -cm -t "$t_stamp" headless.apkovl.tar.gz* doas rm -rf "$build_path" fi diff --git a/overlay/usr/local/bin/headless_bootstrap b/overlay/usr/local/bin/headless_bootstrap index 6ba5a96..04f2e1f 100755 --- a/overlay/usr/local/bin/headless_bootstrap +++ b/overlay/usr/local/bin/headless_bootstrap @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: Copyright 2022-2023, macmpi # SPDX-License-Identifier: MIT -HDLSBSTRP_VERSION="1.1" +HDLSBSTRP_VERSION="1.2" _apk() { local cmd="$1" @@ -82,6 +82,7 @@ cat <<-EOF >> /tmp/.trash/headless_cleanup grep -q "ttyGS0" /etc/securetty || echo "ttyGS0" >> /etc/securetty /sbin/getty -L 115200 ttyGS0 vt100 & fi + exit 0 EOF chmod +x /tmp/.trash/headless_cleanup } @@ -140,39 +141,78 @@ echo "$keygen_stance" >> /etc/conf.d/sshd rc-service sshd restart } +_updt_apkovl() { +## update apkovl overlay file & eventually reboot +# URL redirects to apkovl file on github master: is.gd shortener provides basic analytics. +# Analytics are public and can be checked at https://is.gd/stats.php?url=apkovl_master +# Privacy policy: https://is.gd/privacy.php + +local file_url="https://is.gd/apkovl_master" +local sha_url="https://github.com/macmpi/alpine-linux-headless-bootstrap/raw/main/headless.apkovl.tar.gz.sha512" +local updt_status="failed, keeping original version" +_logger "Updating overlay file..." + +# wget -q -O /tmp/sha -T 10 "$sha_url" > /dev/null 2>&1 && \ +if wget -q -O /tmp/apkovl -T 10 "$file_url" > /dev/null 2>&1 && \ +echo "36243ca58766232a1ff996de611724cee295109f981f3eb5d4b6df916c856036c002abd0cd58266602f3fcbf22777c1bfd1fb891888e864294b86dba366f6f2e toto" > /tmp/sha && \ + [ "$( sha512sum /tmp/apkovl | awk '{print $1}' )" = "$( awk '{print $1}' /tmp/sha )" ]; then + _is_ro && mount -o remount,rw "${ovlpath}" + cp /tmp/apkovl "${ovl}" + _is_ro && mount -o remount,ro "${ovlpath}" + ! [ "$( sha512sum "${ovl}" | awk '{print $1}' )" = "$( awk '{print $1}' /tmp/sha )" ] && \ + _logger "Bad update: original apkovl file may be altered, please check!..." && return 1 + updt_status="successful" +fi +rm -f /tmp/apkovl /tmp/sha +_logger "Update $updt_status" +[ "$updt_status" = "successful" ] || return 1 +# reboot if specified in auto-updt file (and no ssh session ongoing nor unattended.sh script available) +! pgrep -a -P "$( cat /run/sshd.pid 2>/dev/null )" 2>/dev/null | grep -q "sshd: root@pts" && \ + ! [ -f "${ovlpath}"/unattended.sh ] && \ + grep -q "^reboot$" "${ovlpath}"/auto-updt && \ + _logger "Will reboot in 3sec..." && sleep 3 && reboot +exit 0 +} + _tst_version() { -# Tested URL redirects to github project page: is.gd shortener provides basic analytics. +## Compare current version with latest online, notify & eventally calls for update +# URL redirects to github project page: is.gd shortener provides basic analytics. # Analytics are public and can be checked at https://is.gd/stats.php?url=apkovl_run # Privacy policy: https://is.gd/privacy.php local new_vers="" -local status="failed" local ref="/macmpi/alpine-linux-headless-bootstrap/releases/tag/v" -if wget -q -O /tmp/homepg -T 10 https://is.gd/apkovl_run > /dev/null 2>&1; then - status="success" +local url="https://is.gd/apkovl_run" + +if wget -q -O /tmp/homepg -T 10 "$url" > /dev/null 2>&1; then + _logger "Internet access: success" ver="$( grep -o "$ref.*\"" /tmp/homepg | grep -Eo '[0-9]+[\.[0-9]+]*' )" rm -f /tmp/homepg - [ -n "$ver" ] && ! [ "$ver" = "$HDLSBSTRP_VERSION" ] && \ - new_vers="!! Version $ver is available on Github project page !!" && \ - _logger "$new_vers" && \ + if [ -n "$ver" ] && ! [ "$ver" = "$HDLSBSTRP_VERSION" ]; then + new_vers="!! Version $ver is available on Github project page !!" + _logger "$new_vers" printf '%s\n\n' "$new_vers" >> /tmp/.trash/banner + # Optionally update apkovl if key-file allows it + [ -f "${ovlpath}"/auto-updt ] && _updt_apkovl & + fi +else + _logger "Internet access: failed" fi -_logger "Internet access: $status" + } _setup_networking() { ## Setup Network interfaces -local has_wifi +local has_wifi wlan_lst _has_wifi() { return "$has_wifi"; } - -find /sys/class/ieee80211/*/device/net/* -maxdepth 0 -type d -exec basename {} \; > /tmp/.wlan_list 2>/dev/null -[ -s /tmp/.wlan_list ] && [ -f "${ovlpath}"/wpa_supplicant.conf ] +wlan_lst="$( find /sys/class/ieee80211/*/device/net/* -maxdepth 0 -type d -exec sh -c 'printf %s\| "${0##*/}"' {} \; 2>/dev/null )" +wlan_lst="${wlan_lst%\|}" +[ -n "$wlan_lst" ] && [ -f "${ovlpath}"/wpa_supplicant.conf ] has_wifi=$? if _has_wifi; then _logger "Configuring wifi..." _apk add wpa_supplicant _preserve "/etc/wpa_supplicant/wpa_supplicant.conf" install -m600 "${ovlpath}"/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf - rc-service wpa_supplicant restart else _logger "No wifi interface or SSID/pass file supplied" fi @@ -202,24 +242,31 @@ if ! install -m644 "${ovlpath}"/interfaces /etc/network/interfaces > /dev/null 2 EOF ;; *) - _has_wifi && grep -q "$INTERFACE" /tmp/.wlan_list && \ + # According to below we could rely on DEVTYPE for wlan devices + # https://lists.freedesktop.org/archives/systemd-devel/2014-January/015999.html + # but...some wlan might still be ill-behaved: use wlan_lst + # shellcheck disable=SC2169 # ash does support string replacement + _has_wifi && ! [ "${wlan_lst/$INTERFACE/}" = "$wlan_lst" ] && \ cat <<-EOF >> /etc/network/interfaces auto $INTERFACE iface $INTERFACE inet dhcp EOF + # ensure considered gadget interface is actually connected over USB (may have several) [ "$DEVTYPE" = "gadget" ] && \ - cat <<-EOF >> /etc/network/interfaces && cat <<-EOF > /etc/resolv.conf - auto $INTERFACE - iface $INTERFACE inet static - address 10.42.0.2/24 - gateway 10.42.0.1 + ! [ "$( find -L /sys/class/udc/*/device/gadget*/net/"$INTERFACE" -maxdepth 0 -exec \ + sh -c 'cat "${0%/device*}"/current_speed' {} \; )" = "UNKNOWN" ] && \ + cat <<-EOF >> /etc/network/interfaces && cat <<-EOF > /etc/resolv.conf + auto $INTERFACE + iface $INTERFACE inet static + address 10.42.0.2/24 + gateway 10.42.0.1 - EOF - nameserver 208.67.222.222 - nameserver 208.67.220.220 + EOF + nameserver 208.67.222.222 + nameserver 208.67.220.220 - EOF + EOF ;; esac done @@ -234,20 +281,22 @@ _preserve "/etc/hostname" echo "alpine-headless" > /etc/hostname hostname -F /etc/hostname +_has_wifi && grep -qE "$wlan_lst" /etc/network/interfaces && \ + rc-service wpa_supplicant restart rc-service networking restart -rm -f /tmp/.wlan_list } _setup_gadget() { ## load composite USB Serial/USB Ethernel driver & setup terminal _logger "Enabling USB-gadget Serial and Ethernet ports" -lsmod | grep -q "dwc2" || modprobe -qs dwc2 # remove conflicting modules in case they were initially loaded (cmdline.txt) modprobe -rq g_serial g_ether g_cdc modprobe -q g_cdc && sleep 1 -# once driver has settled check if cable is connected: unload if not -[ "$( cat "$udc_gadget"/current_speed )" = "UNKNOWN" ] && \ - _logger "USB cable not connected !!" && modprobe -rq g_cdc && return 1 +# once driver has settled check if any gadget port is connected over USB: unload driver if none +[ "$( find -L /sys/class/udc/*/current_speed -print0 | \ + xargs -0 cat | \ + grep -cv "UNKNOWN" )" = "0" ] && \ + _logger "no USB cable connected !!" && modprobe -rq g_cdc && return 1 # default serial config: xon/xoff flow control stty -g -F /dev/ttyGS0 >/dev/null 2>&1 @@ -272,10 +321,12 @@ _logger "Alpine Linux headless bootstrap v$HDLSBSTRP_VERSION by macmpi" # help randomness for wpa_supplicant and sshd (urandom until 3.16) rc-service seedrng restart || rc-service urandom restart -# setup USB gadget mode if such device mode is enabled -udc_gadget="$( dirname "$( find -L /sys/class/udc/* -maxdepth 2 -type f -name "is_a_peripheral" 2>/dev/null)" )" -[ "$( cat "$udc_gadget"/is_a_peripheral 2>/dev/null )" = "0" ] && \ - _setup_gadget +# setup USB gadget ports if some ports are enabled in peripheral mode +# Note: we assume dwc2/dwc3 is pre-loaded, we just check mode +[ "$( find -L /sys/class/udc/*/is_a_peripheral -print0 2>/dev/null | \ + xargs -0 cat 2>/dev/null | \ + grep -c "0" )" -ge "1" ] && \ + _setup_gadget # Determine ovl file location # grab used ovl filename from dmesg @@ -291,8 +342,10 @@ fi # Create banner file warn="" -grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; RO=$? -[ "$RO" -eq "0" ] && warn="(remount partition rw!)" +grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; is_ro=$? +_is_ro() { return "$is_ro"; } + +_is_ro && warn="(remount partition rw!)" cat <<-EOF > /tmp/.trash/banner Alpine Linux headless bootstrap v$HDLSBSTRP_VERSION by macmpi diff --git a/sample_auto-updt b/sample_auto-updt new file mode 100644 index 0000000..5fbe9ba --- /dev/null +++ b/sample_auto-updt @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: Copyright 2022-2023, macmpi +# SPDX-License-Identifier: MIT + +# Automated reboot after update is cancelled if: +# - there is an opened ssh session +# - unattended.sh script is provided + +# Uncomment line below to enable reboot after update +#reboot + diff --git a/sample_unattended.sh b/sample_unattended.sh index 110e74f..c03ba8f 100644 --- a/sample_unattended.sh +++ b/sample_unattended.sh @@ -37,10 +37,11 @@ else fi # also works in case volume is mounted read-only -grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; RO=$? -[ "$RO" -eq "0" ] && mount -o remount,rw "${ovlpath}" +grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; is_ro=$? +_is_ro() { return "$is_ro"; } +_is_ro && mount -o remount,rw "${ovlpath}" rm -f "${ovl}" -[ "$RO" -eq "0" ] && mount -o remount,ro "${ovlpath}" +_is_ro && mount -o remount,ro "${ovlpath}" ########################################################