Enhance first-boot script and documentation with config file support
Introduce a configuration file (`first-boot.conf`) to allow users to override default script variables without modifying the script directly. Update the first-boot script to load this config file from multiple locations, enhancing flexibility in customization. Revise documentation to guide users on how to utilize the config file for setting variables like FILE_SERVER, HOSTNAME, and PACKAGES, improving the overall user experience during first boot operations.
This commit is contained in:
@@ -1,26 +1,51 @@
|
||||
#!/bin/bash
|
||||
# First-boot: packages, Chromium kiosk, rpd-labwc + touch, reTerminal DM drivers.
|
||||
# Run by cloud-init (user-data-remote-gnss.example). Run as root.
|
||||
# Optional: copy first-boot.conf.example to first-boot.conf and edit; it is loaded
|
||||
# from the script dir, /tmp/first-boot.conf, or /etc/cm4-provisioning/first-boot.conf.
|
||||
|
||||
set -e
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# --- Constants ---
|
||||
# All first-boot assets live in portal-files/first-boot/ on the file server.
|
||||
FILE_SERVER="http://10.20.50.1:5000/files/first-boot"
|
||||
HOSTNAME="guard"
|
||||
PI_USER="pi"
|
||||
# --- Defaults (overridden by first-boot.conf if present) ---
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-.}")" 2>/dev/null && pwd)"
|
||||
FILE_SERVER="${FILE_SERVER:-http://10.20.50.1:5000/files/first-boot}"
|
||||
HOSTNAME="${HOSTNAME:-guard}"
|
||||
PI_USER="${PI_USER:-pi}"
|
||||
LOGFILE="${LOGFILE:-/var/log/first-boot.log}"
|
||||
PLYMOUTH_DIR="${PLYMOUTH_DIR:-/usr/share/plymouth/themes/custom}"
|
||||
WALLPAPER_PATH="${WALLPAPER_PATH:-/usr/share/rpd-wallpaper/splash.png}"
|
||||
PACKAGES="${PACKAGES:-git chromium wmctrl openssh-server swaybg wlr-randr maliit-keyboard xinput-calibrator}"
|
||||
LIGHTDM_SESSION="${LIGHTDM_SESSION:-rpd-labwc}"
|
||||
GTK_THEME_NAME="${GTK_THEME_NAME:-PiXnoir}"
|
||||
WALLPAPER_MODE="${WALLPAPER_MODE:-crop}"
|
||||
DSI_ROTATE="${DSI_ROTATE:-90}"
|
||||
SWIOTLB_SIZE="${SWIOTLB_SIZE:-65536}"
|
||||
RETERMINAL_DEVICE="${RETERMINAL_DEVICE:-reTerminal-DM}"
|
||||
RETERMINAL_REPO_URL="${RETERMINAL_REPO_URL:-https://github.com/Seeed-Studio/seeed-linux-dtoverlays}"
|
||||
ONESHOT_SCRIPTS="${ONESHOT_SCRIPTS:-}"
|
||||
|
||||
# --- Load config file (first found) ---
|
||||
FIRST_BOOT_CONF=""
|
||||
for _f in "$SCRIPT_DIR/first-boot.conf" /tmp/first-boot.conf /etc/cm4-provisioning/first-boot.conf; do
|
||||
if [[ -f "$_f" ]]; then
|
||||
# shellcheck source=first-boot.conf.example
|
||||
set -a && source "$_f" && set +a
|
||||
FIRST_BOOT_CONF="$_f"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# --- Derived paths ---
|
||||
PI_HOME="/home/$PI_USER"
|
||||
AUTOSTART="$PI_HOME/.config/autostart"
|
||||
LOGFILE="/var/log/first-boot.log"
|
||||
PLYMOUTH_DIR="/usr/share/plymouth/themes/custom"
|
||||
WALLPAPER_PATH="/usr/share/rpd-wallpaper/splash.png"
|
||||
|
||||
# --- Logging ---
|
||||
log() { echo "[$(date -Iseconds)] $*"; }
|
||||
exec > >(tee -a "$LOGFILE") 2>&1
|
||||
log "=== first-boot.sh started ==="
|
||||
log "FILE_SERVER=$FILE_SERVER PI_USER=$PI_USER LOGFILE=$LOGFILE"
|
||||
[[ -n "$FIRST_BOOT_CONF" ]] && log "Config loaded from $FIRST_BOOT_CONF" || log "Using built-in defaults (no config file found)"
|
||||
log "FILE_SERVER=$FILE_SERVER PI_USER=$PI_USER HOSTNAME=$HOSTNAME LOGFILE=$LOGFILE"
|
||||
|
||||
# --- 0. Hostname and /etc/hosts (avoids "unable to resolve host" with sudo) ---
|
||||
log "--- Hostname: $HOSTNAME ---"
|
||||
@@ -57,9 +82,8 @@ install_oneshot() {
|
||||
log "--- Installing packages ---"
|
||||
log "Running apt-get update ..."
|
||||
apt-get update -qq
|
||||
log "Installing: git chromium wmctrl openssh-server swaybg wlr-randr maliit-keyboard xinput-calibrator"
|
||||
apt-get install -y -qq git chromium wmctrl openssh-server \
|
||||
swaybg wlr-randr maliit-keyboard xinput-calibrator
|
||||
log "Installing: $PACKAGES"
|
||||
apt-get install -y -qq $PACKAGES
|
||||
log "Packages installed successfully"
|
||||
|
||||
# --- 2. Dirs and kiosk files from file server ---
|
||||
@@ -99,10 +123,10 @@ if curl -fsSL "${FILE_SERVER}/splash.png" -o "$PLYMOUTH_DIR/splash.png"; then
|
||||
PCMANFM_DESKTOP="$PI_HOME/.config/pcmanfm/$PROFILE/desktop-items-0.conf"
|
||||
mkdir -p "$(dirname "$PCMANFM_DESKTOP")"
|
||||
if [[ ! -f "$PCMANFM_DESKTOP" ]]; then
|
||||
printf '%s\n' '[*]' "wallpaper=$WALLPAPER_PATH" 'wallpaper_mode=crop' 'wallpaper_common=1' > "$PCMANFM_DESKTOP"
|
||||
printf '%s\n' '[*]' "wallpaper=$WALLPAPER_PATH" "wallpaper_mode=$WALLPAPER_MODE" 'wallpaper_common=1' > "$PCMANFM_DESKTOP"
|
||||
else
|
||||
grep -q '^wallpaper=' "$PCMANFM_DESKTOP" && sed -i "s|^wallpaper=.*|wallpaper=$WALLPAPER_PATH|" "$PCMANFM_DESKTOP" || echo "wallpaper=$WALLPAPER_PATH" >> "$PCMANFM_DESKTOP"
|
||||
grep -q '^wallpaper_mode=' "$PCMANFM_DESKTOP" && sed -i 's/^wallpaper_mode=.*/wallpaper_mode=crop/' "$PCMANFM_DESKTOP" || echo 'wallpaper_mode=crop' >> "$PCMANFM_DESKTOP"
|
||||
grep -q '^wallpaper_mode=' "$PCMANFM_DESKTOP" && sed -i "s/^wallpaper_mode=.*/wallpaper_mode=$WALLPAPER_MODE/" "$PCMANFM_DESKTOP" || echo "wallpaper_mode=$WALLPAPER_MODE" >> "$PCMANFM_DESKTOP"
|
||||
fi
|
||||
chown -R "$PI_USER:$PI_USER" "$(dirname "$PCMANFM_DESKTOP")"
|
||||
done
|
||||
@@ -122,9 +146,9 @@ else
|
||||
fi
|
||||
# Raspberry Pi OS may apply main lightdm.conf after .conf.d; force session in main config too
|
||||
if [[ -f /etc/lightdm/lightdm.conf ]]; then
|
||||
sed -i 's/^user-session=.*/user-session=rpd-labwc/' /etc/lightdm/lightdm.conf
|
||||
sed -i 's/^autologin-session=.*/autologin-session=rpd-labwc/' /etc/lightdm/lightdm.conf
|
||||
log "Patched /etc/lightdm/lightdm.conf to use rpd-labwc"
|
||||
sed -i "s/^user-session=.*/user-session=$LIGHTDM_SESSION/" /etc/lightdm/lightdm.conf
|
||||
sed -i "s/^autologin-session=.*/autologin-session=$LIGHTDM_SESSION/" /etc/lightdm/lightdm.conf
|
||||
log "Patched /etc/lightdm/lightdm.conf to use $LIGHTDM_SESSION"
|
||||
fi
|
||||
|
||||
# --- 5. Maliit on-screen keyboard (from file server) ---
|
||||
@@ -137,29 +161,33 @@ log "--- Dark theme ---"
|
||||
GTK_SETTINGS="$PI_HOME/.config/gtk-3.0/settings.ini"
|
||||
mkdir -p "$(dirname "$GTK_SETTINGS")"
|
||||
if [[ ! -f "$GTK_SETTINGS" ]]; then
|
||||
printf '%s\n' '[Settings]' 'gtk-application-prefer-dark-theme=1' 'gtk-theme-name=PiXnoir' > "$GTK_SETTINGS"
|
||||
printf '%s\n' '[Settings]' 'gtk-application-prefer-dark-theme=1' "gtk-theme-name=$GTK_THEME_NAME" > "$GTK_SETTINGS"
|
||||
else
|
||||
grep -q '^gtk-application-prefer-dark-theme=' "$GTK_SETTINGS" && sed -i 's/^gtk-application-prefer-dark-theme=.*/gtk-application-prefer-dark-theme=1/' "$GTK_SETTINGS" || echo 'gtk-application-prefer-dark-theme=1' >> "$GTK_SETTINGS"
|
||||
grep -q '^gtk-theme-name=' "$GTK_SETTINGS" && sed -i 's/^gtk-theme-name=.*/gtk-theme-name=PiXnoir/' "$GTK_SETTINGS" || echo 'gtk-theme-name=PiXnoir' >> "$GTK_SETTINGS"
|
||||
grep -q '^gtk-theme-name=' "$GTK_SETTINGS" && sed -i "s/^gtk-theme-name=.*/gtk-theme-name=$GTK_THEME_NAME/" "$GTK_SETTINGS" || echo "gtk-theme-name=$GTK_THEME_NAME" >> "$GTK_SETTINGS"
|
||||
fi
|
||||
# Fallback if PiXnoir not installed (e.g. older image): Adwaita-dark
|
||||
log "Set dark theme (PiXnoir) in gtk-3.0/settings.ini"
|
||||
# Fallback if theme not installed (e.g. older image): Adwaita-dark
|
||||
log "Set dark theme ($GTK_THEME_NAME) in gtk-3.0/settings.ini"
|
||||
chown -R "$PI_USER:$PI_USER" "$PI_HOME/.config"
|
||||
|
||||
# --- 6. reTerminal DM drivers (Seeed) ---
|
||||
log "--- reTerminal DM drivers ---"
|
||||
REPO_DIR="/tmp/seeed-linux-dtoverlays"
|
||||
log "Cloning seeed-linux-dtoverlays to $REPO_DIR ..."
|
||||
git clone --depth 1 https://github.com/Seeed-Studio/seeed-linux-dtoverlays "$REPO_DIR"
|
||||
# Script must run from repo root (it uses pwd for MOD_PATH). On bookworm+ --compat-kernel is not supported.
|
||||
log "Running reTerminal.sh --device reTerminal-DM from $REPO_DIR ..."
|
||||
if ( cd "$REPO_DIR" && "$REPO_DIR/scripts/reTerminal.sh" --device reTerminal-DM ); then
|
||||
log "reTerminal DM drivers installed (reboot will apply)"
|
||||
if [[ -n "$RETERMINAL_REPO_URL" ]]; then
|
||||
log "--- reTerminal DM drivers ---"
|
||||
REPO_DIR="/tmp/seeed-linux-dtoverlays"
|
||||
log "Cloning seeed-linux-dtoverlays to $REPO_DIR ..."
|
||||
git clone --depth 1 "$RETERMINAL_REPO_URL" "$REPO_DIR"
|
||||
# Script must run from repo root (it uses pwd for MOD_PATH). On bookworm+ --compat-kernel is not supported.
|
||||
log "Running reTerminal.sh --device $RETERMINAL_DEVICE from $REPO_DIR ..."
|
||||
if ( cd "$REPO_DIR" && "$REPO_DIR/scripts/reTerminal.sh" --device "$RETERMINAL_DEVICE" ); then
|
||||
log "reTerminal DM drivers installed (reboot will apply)"
|
||||
else
|
||||
log "WARNING: reTerminal.sh failed (see log above). Display/touch may still work; you can retry later with: cd $REPO_DIR && sudo ./scripts/reTerminal.sh --device $RETERMINAL_DEVICE"
|
||||
fi
|
||||
log "Removing $REPO_DIR"
|
||||
rm -rf "$REPO_DIR"
|
||||
else
|
||||
log "WARNING: reTerminal.sh failed (see log above). Display/touch may still work; you can retry later with: cd $REPO_DIR && sudo ./scripts/reTerminal.sh --device reTerminal-DM"
|
||||
log "--- Skipping reTerminal drivers (RETERMINAL_REPO_URL not set) ---"
|
||||
fi
|
||||
log "Removing $REPO_DIR"
|
||||
rm -rf "$REPO_DIR"
|
||||
|
||||
# --- 6b. Re-apply splash and display (Seeed script sets disable_splash=1 and can duplicate Plymouth theme) ---
|
||||
log "--- Re-applying boot splash and Plymouth theme ---"
|
||||
@@ -186,21 +214,29 @@ update-initramfs -u -k all 2>/dev/null || true
|
||||
CMDLINE_PATH="/boot/firmware/cmdline.txt"
|
||||
[[ -f "$CMDLINE_PATH" ]] || CMDLINE_PATH="/boot/cmdline.txt"
|
||||
if [[ -f "$CMDLINE_PATH" ]]; then
|
||||
if ! grep -q 'swiotlb=' "$CMDLINE_PATH"; then
|
||||
sed -i 's/rootwait/rootwait swiotlb=65536/' "$CMDLINE_PATH"
|
||||
log "Added swiotlb=65536 to kernel cmdline (vc4-drm / DSI)"
|
||||
if [[ -n "$SWIOTLB_SIZE" ]] && ! grep -q 'swiotlb=' "$CMDLINE_PATH"; then
|
||||
sed -i "s/rootwait/rootwait swiotlb=$SWIOTLB_SIZE/" "$CMDLINE_PATH"
|
||||
log "Added swiotlb=$SWIOTLB_SIZE to kernel cmdline (vc4-drm / DSI)"
|
||||
fi
|
||||
# Persistent rotation for DSI-1 (KMS): append at end of single line. 90 = 90° clockwise.
|
||||
if ! grep -q 'video=DSI-1:rotate=' "$CMDLINE_PATH"; then
|
||||
sed -i 's/$/ video=DSI-1:rotate=90/' "$CMDLINE_PATH"
|
||||
log "Added video=DSI-1:rotate=90 to kernel cmdline (DSI rotation)"
|
||||
if [[ -n "$DSI_ROTATE" ]] && ! grep -q 'video=DSI-1:rotate=' "$CMDLINE_PATH"; then
|
||||
sed -i "s/\$/ video=DSI-1:rotate=$DSI_ROTATE/" "$CMDLINE_PATH"
|
||||
log "Added video=DSI-1:rotate=$DSI_ROTATE to kernel cmdline (DSI rotation)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- 7. One-shots (wallpaper already set in pcmanfm config above; rotation is via cmdline.txt) ---
|
||||
log "--- One-shot scripts (if any) ---"
|
||||
# Rotation is set persistently in cmdline.txt (video=DSI-1:rotate=90), not via one-shot script.
|
||||
log "Rotation is set via kernel cmdline (video=DSI-1:rotate=90)"
|
||||
if [[ -n "$DSI_ROTATE" ]]; then
|
||||
log "Rotation is set via kernel cmdline (video=DSI-1:rotate=$DSI_ROTATE)"
|
||||
fi
|
||||
if [[ -n "$ONESHOT_SCRIPTS" ]]; then
|
||||
for _name in $ONESHOT_SCRIPTS; do
|
||||
install_oneshot "$_name" || true
|
||||
done
|
||||
else
|
||||
log "No one-shot scripts configured (ONESHOT_SCRIPTS empty)"
|
||||
fi
|
||||
|
||||
# --- 8. Allow pi to append to first-boot.log (for one-shot scripts) ---
|
||||
chmod 666 "$LOGFILE"
|
||||
|
||||
Reference in New Issue
Block a user