version 1.2
New feature: auto-update apkovl file with latest release on master gadget: improved setup if several ports available and/or some unconnected wlan: only install & start wpa_supplicant if needed updated doc
This commit is contained in:
parent
4026274721
commit
e7bd00c1df
15
README.md
15
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.
|
- `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.
|
- `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).
|
- `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).
|
||||||
|
- `auto-updt` (*optional*): allow apkovl file automatic update with latest from master branch. If it contains *reboot* keyword all in one line, system will reboot after succesful update (unless ssh session is active or `unattended.sh` script is available).
|
||||||
|
|
||||||
**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`.
|
|
||||||
|
|
||||||
Main execution steps are logged: `cat /var/log/messages | grep headless`.
|
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 accordingly, 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.
|
[^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).
|
[^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).
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
003cb6812a4db690db522bb26de14f83d55e2c0b2a8d626a35c90bb9c6cce3181c605f6b51722cd54c712815952faf1072336eb932f80e683748869e27027afb headless.apkovl.tar.gz
|
3
make.sh
3
make.sh
|
@ -30,7 +30,8 @@ if [ -n "$build_path" ]; then
|
||||||
doas tar cv -C "$build_path"/overlay --no-recursion \
|
doas tar cv -C "$build_path"/overlay --no-recursion \
|
||||||
$(doas find "$build_path"/overlay/ | sed "s|$build_path/overlay/||" | sort | xargs ) | \
|
$(doas find "$build_path"/overlay/ | sed "s|$build_path/overlay/||" | sort | xargs ) | \
|
||||||
gzip -c9n > headless.apkovl.tar.gz
|
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"
|
doas rm -rf "$build_path"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# SPDX-FileCopyrightText: Copyright 2022-2023, macmpi
|
# SPDX-FileCopyrightText: Copyright 2022-2023, macmpi
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
HDLSBSTRP_VERSION="1.1"
|
HDLSBSTRP_VERSION="1.2"
|
||||||
|
|
||||||
_apk() {
|
_apk() {
|
||||||
local cmd="$1"
|
local cmd="$1"
|
||||||
|
@ -27,14 +27,14 @@ _apk() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_preserve() {
|
_preserve() {
|
||||||
# create a back-up of element (file, folder, symlink)
|
# Create a back-up of element (file, folder, symlink).
|
||||||
[ -z "${1}" ] && return 1
|
[ -z "${1}" ] && return 1
|
||||||
[ -e "${1}" ] && cp -a "${1}" "${1}".orig
|
[ -e "${1}" ] && cp -a "${1}" "${1}".orig
|
||||||
}
|
}
|
||||||
|
|
||||||
_restore() {
|
_restore() {
|
||||||
# remove element (file, folder, symlink) and replace by
|
# Remove element (file, folder, symlink) and replace by
|
||||||
# previous back-up if available
|
# previous back-up if available.
|
||||||
[ -z "${1}" ] && return 1
|
[ -z "${1}" ] && return 1
|
||||||
rm -rf "${1}"
|
rm -rf "${1}"
|
||||||
[ -e "${1}".orig ] && mv -f "${1}".orig "${1}"
|
[ -e "${1}".orig ] && mv -f "${1}".orig "${1}"
|
||||||
|
@ -46,9 +46,9 @@ alias _logger='logger -st "${0##*/}"'
|
||||||
##### End of part to be duplicated into headless_cleanup (do not alter!)
|
##### End of part to be duplicated into headless_cleanup (do not alter!)
|
||||||
|
|
||||||
_prep_cleanup() {
|
_prep_cleanup() {
|
||||||
## Prep for final headless_cleanup
|
## Prep for final headless_cleanup:
|
||||||
# clears any installed packages and settings
|
# clears any installed packages and settings.
|
||||||
# copy begininng of this file to keep functions
|
# Copy begininng of this file to keep functions.
|
||||||
sed -n '/^#* End .*alter!)$/q;p' /usr/local/bin/headless_bootstrap >/tmp/.trash/headless_cleanup
|
sed -n '/^#* End .*alter!)$/q;p' /usr/local/bin/headless_bootstrap >/tmp/.trash/headless_cleanup
|
||||||
cat <<-EOF >>/tmp/.trash/headless_cleanup
|
cat <<-EOF >>/tmp/.trash/headless_cleanup
|
||||||
# Redirect stdout and errors to console as service won't show messages
|
# Redirect stdout and errors to console as service won't show messages
|
||||||
|
@ -64,31 +64,32 @@ cat <<-EOF >> /tmp/.trash/headless_cleanup
|
||||||
_restore "/etc/hostname"
|
_restore "/etc/hostname"
|
||||||
rm -f /etc/modprobe.d/headless_gadget.conf
|
rm -f /etc/modprobe.d/headless_gadget.conf
|
||||||
|
|
||||||
# remove from boot service to avoid spurious openrc recalls from unattended script
|
# Remove from boot service to avoid spurious openrc recalls from unattended script.
|
||||||
rm -f /etc/runlevels/default/headless_bootstrap
|
rm -f /etc/runlevels/default/headless_bootstrap
|
||||||
rm -f /usr/local/bin/headless_bootstrap
|
rm -f /usr/local/bin/headless_bootstrap
|
||||||
|
|
||||||
# Run unattended script if available
|
# Run unattended script if available.
|
||||||
install -m755 "${ovlpath}"/unattended.sh /tmp/headless_unattended > /dev/null 2>&1 && \
|
install -m755 ${ovlpath}/unattended.sh /tmp/headless_unattended >/dev/null 2>&1 && \
|
||||||
_logger "Starting headless_unattended service" && \
|
_logger "Starting headless_unattended service" && \
|
||||||
rc-service headless_unattended start
|
rc-service headless_unattended start
|
||||||
|
|
||||||
rm -f /etc/init.d/headless_*
|
rm -f /etc/init.d/headless_*
|
||||||
_logger "Clean-up done, enjoy !"
|
_logger "Clean-up done, enjoy !"
|
||||||
cat /tmp/.trash/banner >/dev/console
|
cat /tmp/.trash/banner >/dev/console
|
||||||
if [ -c /dev/ttyGS0 ]; then
|
if [ -c /dev/ttyGS${gdgt_id} ]; then
|
||||||
# Enabling terminal login into ttyGS0 serial for 60 sec
|
# Enabling terminal login into valid serial port:
|
||||||
# no choice than making permanent change to pre 3.19 versions of /etc/securetty
|
# no choice than making permanent change to /etc/securetty (Alpine 3.19 already has ttyGS0).
|
||||||
grep -q "ttyGS0" /etc/securetty || echo "ttyGS0" >> /etc/securetty
|
grep -q "ttyGS${gdgt_id}" /etc/securetty || echo "ttyGS${gdgt_id}" >>/etc/securetty
|
||||||
/sbin/getty -L 115200 ttyGS0 vt100 &
|
/sbin/getty -L 115200 /dev/ttyGS${gdgt_id} vt100 &
|
||||||
fi
|
fi
|
||||||
|
exit 0
|
||||||
EOF
|
EOF
|
||||||
chmod +x /tmp/.trash/headless_cleanup
|
chmod +x /tmp/.trash/headless_cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
_setup_sshd() {
|
_setup_sshd() {
|
||||||
## Setup temporary SSH server (root login, no password)
|
## Setup temporary SSH server (root login, no password):
|
||||||
# We use some bundled (or optionaly provided) keys to avoid generation at startup and save time
|
# we use some bundled (or optionaly provided) keys to avoid generation at startup and save time.
|
||||||
_apk add openssh-server
|
_apk add openssh-server
|
||||||
_preserve "/etc/ssh/sshd_config"
|
_preserve "/etc/ssh/sshd_config"
|
||||||
_preserve "/etc/conf.d/sshd"
|
_preserve "/etc/conf.d/sshd"
|
||||||
|
@ -98,7 +99,7 @@ cat <<-EOF > /etc/ssh/sshd_config
|
||||||
Banner /tmp/.trash/banner
|
Banner /tmp/.trash/banner
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Client authorized_keys or no authentication
|
# Client authorized_keys or no authentication.
|
||||||
if install -m600 "${ovlpath}"/authorized_keys /tmp/.trash/authorized_keys >/dev/null 2>&1; then
|
if install -m600 "${ovlpath}"/authorized_keys /tmp/.trash/authorized_keys >/dev/null 2>&1; then
|
||||||
_logger "Enabling public key SSH authentication..."
|
_logger "Enabling public key SSH authentication..."
|
||||||
cat <<-EOF >>/etc/ssh/sshd_config
|
cat <<-EOF >>/etc/ssh/sshd_config
|
||||||
|
@ -119,7 +120,7 @@ fi
|
||||||
# or use bundeled ones (not stored)
|
# or use bundeled ones (not stored)
|
||||||
local keygen_stance="sshd_disable_keygen=yes"
|
local keygen_stance="sshd_disable_keygen=yes"
|
||||||
if install -m600 "${ovlpath}"/ssh_host_*_key* /etc/ssh/ >/dev/null 2>&1; then
|
if install -m600 "${ovlpath}"/ssh_host_*_key* /etc/ssh/ >/dev/null 2>&1; then
|
||||||
# check for empty key within injected ones: if found, generate new keys
|
# Check for empty key within injected ones: if found, generate new keys.
|
||||||
if find /etc/ssh/ -maxdepth 1 -type f -name 'ssh_host_*_key*' -empty | grep -q .; then
|
if find /etc/ssh/ -maxdepth 1 -type f -name 'ssh_host_*_key*' -empty | grep -q .; then
|
||||||
rm /etc/ssh/ssh_host_*_key*
|
rm /etc/ssh/ssh_host_*_key*
|
||||||
keygen_stance=""
|
keygen_stance=""
|
||||||
|
@ -140,42 +141,72 @@ echo "$keygen_stance" >> /etc/conf.d/sshd
|
||||||
rc-service sshd restart
|
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..."
|
||||||
|
if wget -q -O /tmp/apkovl -T 10 "$file_url" >/dev/null 2>&1 && \
|
||||||
|
wget -q -O /tmp/sha -T 10 "$sha_url" >/dev/null 2>&1 && \
|
||||||
|
[ "$( 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() {
|
_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
|
# Analytics are public and can be checked at https://is.gd/stats.php?url=apkovl_run
|
||||||
# Privacy policy: https://is.gd/privacy.php
|
# Privacy policy: https://is.gd/privacy.php
|
||||||
local new_vers=""
|
local new_vers=""
|
||||||
local status="failed"
|
|
||||||
local ref="/macmpi/alpine-linux-headless-bootstrap/releases/tag/v"
|
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
|
local url="https://is.gd/apkovl_run"
|
||||||
status="success"
|
|
||||||
|
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]+]*' )"
|
ver="$( grep -o "$ref.*\"" /tmp/homepg | grep -Eo '[0-9]+[\.[0-9]+]*' )"
|
||||||
rm -f /tmp/homepg
|
rm -f /tmp/homepg
|
||||||
[ -n "$ver" ] && ! [ "$ver" = "$HDLSBSTRP_VERSION" ] && \
|
if [ -n "$ver" ] && ! [ "$ver" = "$HDLSBSTRP_VERSION" ]; then
|
||||||
new_vers="!! Version $ver is available on Github project page !!" && \
|
new_vers="!! Version $ver is available on Github project page !!"
|
||||||
_logger "$new_vers" && \
|
_logger "$new_vers"
|
||||||
printf '%s\n\n' "$new_vers" >>/tmp/.trash/banner
|
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
|
fi
|
||||||
_logger "Internet access: $status"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setup_networking() {
|
_setup_networking() {
|
||||||
## Setup Network interfaces
|
## Setup network interfaces.
|
||||||
local has_wifi
|
local has_wifi wlan_lst
|
||||||
_has_wifi() { return "$has_wifi"; }
|
_has_wifi() { return "$has_wifi"; }
|
||||||
|
|
||||||
find /sys/class/ieee80211/*/device/net/* -maxdepth 0 -type d -exec basename {} \; > /tmp/.wlan_list 2>/dev/null
|
wlan_lst="$( find /sys/class/net/*/phy80211 -exec \
|
||||||
[ -s /tmp/.wlan_list ] && [ -f "${ovlpath}"/wpa_supplicant.conf ]
|
sh -c 'printf %s\| "$( basename "$( dirname "$0" )" )"' {} \; 2>/dev/null )"
|
||||||
|
wlan_lst="${wlan_lst%\|}"
|
||||||
|
[ -n "$wlan_lst" ] && [ -f "${ovlpath}"/wpa_supplicant.conf ]
|
||||||
has_wifi=$?
|
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
|
|
||||||
|
|
||||||
_preserve "/etc/network/interfaces"
|
_preserve "/etc/network/interfaces"
|
||||||
if ! install -m644 "${ovlpath}"/interfaces /etc/network/interfaces >/dev/null 2>&1; then
|
if ! install -m644 "${ovlpath}"/interfaces /etc/network/interfaces >/dev/null 2>&1; then
|
||||||
|
@ -186,7 +217,7 @@ if ! install -m644 "${ovlpath}"/interfaces /etc/network/interfaces > /dev/null 2
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
for dev in /sys/class/net/*; do
|
for dev in /sys/class/net/*; do
|
||||||
# shellcheck disable=SC2034 # Unused IFINDEX while still sourced from uevent
|
# shellcheck disable=SC2034 # Unused IFINDEX while still sourced from uevent.
|
||||||
local DEVTYPE INTERFACE IFINDEX
|
local DEVTYPE INTERFACE IFINDEX
|
||||||
DEVTYPE=""
|
DEVTYPE=""
|
||||||
# shellcheck source=/dev/null
|
# shellcheck source=/dev/null
|
||||||
|
@ -202,13 +233,19 @@ if ! install -m644 "${ovlpath}"/interfaces /etc/network/interfaces > /dev/null 2
|
||||||
EOF
|
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
|
cat <<-EOF >>/etc/network/interfaces
|
||||||
auto $INTERFACE
|
auto $INTERFACE
|
||||||
iface $INTERFACE inet dhcp
|
iface $INTERFACE inet dhcp
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
# Ensure considered gadget interface is actually the connected one (may have several).
|
||||||
[ "$DEVTYPE" = "gadget" ] && \
|
[ "$DEVTYPE" = "gadget" ] && \
|
||||||
|
find /sys/class/udc/*/device/gadget."${gdgt_id}"/net/"$INTERFACE" -maxdepth 0 >/dev/null 2>&1 && \
|
||||||
cat <<-EOF >>/etc/network/interfaces && cat <<-EOF >/etc/resolv.conf
|
cat <<-EOF >>/etc/network/interfaces && cat <<-EOF >/etc/resolv.conf
|
||||||
auto $INTERFACE
|
auto $INTERFACE
|
||||||
iface $INTERFACE inet static
|
iface $INTERFACE inet static
|
||||||
|
@ -230,35 +267,53 @@ echo "Using following network interfaces:"
|
||||||
cat /etc/network/interfaces
|
cat /etc/network/interfaces
|
||||||
echo "###################################"
|
echo "###################################"
|
||||||
|
|
||||||
|
if _has_wifi && grep -qE "$wlan_lst" /etc/network/interfaces; 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
|
||||||
|
|
||||||
_preserve "/etc/hostname"
|
_preserve "/etc/hostname"
|
||||||
echo "alpine-headless" >/etc/hostname
|
echo "alpine-headless" >/etc/hostname
|
||||||
hostname -F /etc/hostname
|
hostname -F /etc/hostname
|
||||||
|
|
||||||
rc-service networking restart
|
rc-service networking restart
|
||||||
rm -f /tmp/.wlan_list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setup_gadget() {
|
_setup_gadget() {
|
||||||
## load composite USB Serial/USB Ethernel driver & setup terminal
|
## Load composite USB Serial/USB Ethernel driver & setup terminal.
|
||||||
_logger "Enabling USB-gadget Serial and Ethernet ports"
|
_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).
|
||||||
# remove conflicting modules in case they were initially loaded (cmdline.txt)
|
modprobe -r g_serial g_ether g_cdc
|
||||||
modprobe -rq g_serial g_ether g_cdc
|
modprobe g_cdc
|
||||||
modprobe -q g_cdc && sleep 1
|
# Wait for g_cdc to settle and serial ports become available
|
||||||
# once driver has settled check if cable is connected: unload if not
|
timeout 1 sh <<-EOF
|
||||||
[ "$( cat "$udc_gadget"/current_speed )" = "UNKNOWN" ] && \
|
while ! grep -q "ttyGS" /proc/devices; do sleep 0.2; done
|
||||||
_logger "USB cable not connected !!" && modprobe -rq g_cdc && return 1
|
EOF
|
||||||
|
|
||||||
# default serial config: xon/xoff flow control
|
# Determine which gadget ID is connected with USB cable (assume just one max).
|
||||||
stty -g -F /dev/ttyGS0 >/dev/null 2>&1
|
# (setting console to unconnected serial port would block boot)
|
||||||
# notes to users willing to connect from Linux Ubuntu-based host terminal:
|
gdgt_id="$( find /sys/class/udc/*/current_speed -exec \
|
||||||
|
sh -c 'grep -vq "UNKNOWN" "$0" && find ${0/current_speed/}device/gadget.* -maxdepth 0' {} \; \
|
||||||
|
| sed 's/\/.*gadget\.//' )"
|
||||||
|
if [ -c /dev/ttyGS"${gdgt_id}" ]; then
|
||||||
|
# Default serial config: xon/xoff flow control.
|
||||||
|
stty -F /dev/ttyGS"${gdgt_id}"
|
||||||
|
setconsole /dev/ttyGS"${gdgt_id}"
|
||||||
|
# Notes to users willing to connect from Linux Ubuntu-based host terminal:
|
||||||
# - user on host needs to be part of dialout group (reboot required), and
|
# - user on host needs to be part of dialout group (reboot required), and
|
||||||
# - disable spurious AT commands from ModemManager on host-side Gadget serial port
|
# - disable spurious AT commands from ModemManager on host-side Gadget serial port
|
||||||
# you may create a /etc/udev/rules.d/99-ttyacms-gadget.rules as per:
|
# one may create a /etc/udev/rules.d/99-ttyacms-gadget.rules as per:
|
||||||
# https://linux-tips.com/t/prevent-modem-manager-to-capture-usb-serial-devices/284/2
|
# https://linux-tips.com/t/prevent-modem-manager-to-capture-usb-serial-devices/284/2
|
||||||
# ATTRS{idVendor}=="0525" ATTRS{idProduct}=="a4aa", ENV{ID_MM_DEVICE_IGNORE}="1"
|
# ATTRS{idVendor}=="0525" ATTRS{idProduct}=="a4aa", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||||
|
else
|
||||||
setconsole /dev/ttyGS0
|
_logger "USB-gadget port not connected !"
|
||||||
|
modprobe -r g_cdc
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,30 +324,34 @@ setconsole /dev/ttyGS0
|
||||||
exec 1>/dev/console 2>&1
|
exec 1>/dev/console 2>&1
|
||||||
_logger "Alpine Linux headless bootstrap v$HDLSBSTRP_VERSION by macmpi"
|
_logger "Alpine Linux headless bootstrap v$HDLSBSTRP_VERSION by macmpi"
|
||||||
|
|
||||||
# help randomness for wpa_supplicant and sshd (urandom until 3.16)
|
# Help randomness for wpa_supplicant and sshd (urandom until 3.16).
|
||||||
rc-service seedrng restart || rc-service urandom restart
|
rc-service seedrng restart || rc-service urandom restart
|
||||||
|
|
||||||
# setup USB gadget mode if such device mode is enabled
|
# Setup USB gadget ports if some ports are enabled in peripheral mode.
|
||||||
udc_gadget="$( dirname "$( find -L /sys/class/udc/* -maxdepth 2 -type f -name "is_a_peripheral" 2>/dev/null)" )"
|
# Note: we assume dwc2/dwc3 is pre-loaded, we just check mode.
|
||||||
[ "$( cat "$udc_gadget"/is_a_peripheral 2>/dev/null )" = "0" ] && \
|
gdgt_id=""
|
||||||
|
find /sys/class/udc/*/is_a_peripheral -print0 2>/dev/null | \
|
||||||
|
xargs -0 cat 2>/dev/null | grep -q "0" && \
|
||||||
_setup_gadget
|
_setup_gadget
|
||||||
|
|
||||||
# Determine ovl file location
|
# Determine ovl file location.
|
||||||
# grab used ovl filename from dmesg
|
# Grab used ovl filename from dmesg.
|
||||||
ovl="$( dmesg | grep -o 'Loading user settings from .*:' | awk '{print $5}' | sed 's/:.*$//' )"
|
ovl="$( dmesg | grep -o 'Loading user settings from .*:' | awk '{print $5}' | sed 's/:.*$//' )"
|
||||||
if [ -f "${ovl}" ]; then
|
if [ -f "${ovl}" ]; then
|
||||||
ovlpath="$( dirname "$ovl" )"
|
ovlpath="$( dirname "$ovl" )"
|
||||||
else
|
else
|
||||||
# search path again as mountpoint have been changed later in the boot process...
|
# Search path again as mountpoint have been changed later in the boot process...
|
||||||
ovl="$( basename "${ovl}" )"
|
ovl="$( basename "${ovl}" )"
|
||||||
ovlpath=$( find /media -maxdepth 2 -type d -path '*/.*' -prune -o -type f -name "${ovl}" -exec dirname {} \; | head -1 )
|
ovlpath=$( find /media -maxdepth 2 -type d -path '*/.*' -prune -o -type f -name "${ovl}" -exec dirname {} \; | head -1 )
|
||||||
ovl="${ovlpath}/${ovl}"
|
ovl="${ovlpath}/${ovl}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create banner file
|
# Create banner file.
|
||||||
warn=""
|
warn=""
|
||||||
grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; RO=$?
|
grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; is_ro=$?
|
||||||
[ "$RO" -eq "0" ] && warn="(remount partition rw!)"
|
_is_ro() { return "$is_ro"; }
|
||||||
|
|
||||||
|
_is_ro && warn="(remount partition rw!)"
|
||||||
cat <<-EOF >/tmp/.trash/banner
|
cat <<-EOF >/tmp/.trash/banner
|
||||||
|
|
||||||
Alpine Linux headless bootstrap v$HDLSBSTRP_VERSION by macmpi
|
Alpine Linux headless bootstrap v$HDLSBSTRP_VERSION by macmpi
|
||||||
|
@ -306,11 +365,11 @@ cat <<-EOF > /tmp/.trash/banner
|
||||||
|
|
||||||
_setup_networking
|
_setup_networking
|
||||||
|
|
||||||
# Test latest available version online
|
# Test latest available version online.
|
||||||
# Can be skipped by creating a 'opt-out'-named dummy file aside apkovl file
|
# Can be skipped by creating a 'opt-out'-named dummy file aside apkovl file.
|
||||||
[ -f "${ovlpath}"/opt-out ] || _tst_version &
|
[ -f "${ovlpath}"/opt-out ] || _tst_version &
|
||||||
|
|
||||||
# setup sshd unless unattended.sh script prevents it
|
# Setup sshd unless unattended.sh script prevents it.
|
||||||
grep -q "^#NO_SSH$" "${ovlpath}"/unattended.sh >/dev/null 2>&1 \
|
grep -q "^#NO_SSH$" "${ovlpath}"/unattended.sh >/dev/null 2>&1 \
|
||||||
|| _setup_sshd
|
|| _setup_sshd
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -37,10 +37,11 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# also works in case volume is mounted read-only
|
# also works in case volume is mounted read-only
|
||||||
grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; RO=$?
|
grep -q "${ovlpath}.*[[:space:]]ro[[:space:],]" /proc/mounts; is_ro=$?
|
||||||
[ "$RO" -eq "0" ] && mount -o remount,rw "${ovlpath}"
|
_is_ro() { return "$is_ro"; }
|
||||||
|
_is_ro && mount -o remount,rw "${ovlpath}"
|
||||||
rm -f "${ovl}"
|
rm -f "${ovl}"
|
||||||
[ "$RO" -eq "0" ] && mount -o remount,ro "${ovlpath}"
|
_is_ro && mount -o remount,ro "${ovlpath}"
|
||||||
|
|
||||||
########################################################
|
########################################################
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue