clawdie-iso/firstboot/setup-import.sh

189 lines
5.5 KiB
Bash

#!/bin/sh
# Clawdie Shell — Setup Import Module
# Purpose: Import setup.txt + system.env from a writable FAT32 USB partition
# POSIX sh, no Node dependency
set -eu
CONFIG_LABEL="${CONFIG_LABEL:-CLAWDIE}"
CONFIG_MOUNT_POINT="${CONFIG_MOUNT_POINT:-/mnt/clawdie-setup}"
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
clawdie_setup_import_load() {
log_msg "[setup-import] Scanning for config partition"
_part=$(clawdie_setup_import_find_partition)
if [ -z "$_part" ]; then
log_msg "[setup-import] No config partition found — falling through to wizard"
return 0
fi
log_msg "[setup-import] Found config partition: $_part"
mkdir -p "$CONFIG_MOUNT_POINT"
if ! mount -t msdosfs "$_part" "$CONFIG_MOUNT_POINT" 2>/dev/null; then
log_msg "[setup-import] Mount failed on $_part — falling through to wizard"
return 0
fi
_mounted=1
trap 'clawdie_setup_import_cleanup_mount' EXIT INT TERM
if [ -f "$CONFIG_MOUNT_POINT/setup.txt" ]; then
clawdie_setup_import_parse_file "$CONFIG_MOUNT_POINT/setup.txt" setup
fi
if [ -f "$CONFIG_MOUNT_POINT/system.env" ]; then
clawdie_setup_import_parse_file "$CONFIG_MOUNT_POINT/system.env" system
fi
if [ ! -f "$CONFIG_MOUNT_POINT/setup.txt" ]; then
log_msg "[setup-import] setup.txt not on $_part — falling through to wizard"
clawdie_setup_import_cleanup_mount
return 0
fi
clawdie_setup_import_apply_defaults
for _req in ASSISTANT_NAME AGENT_DOMAIN TZ; do
eval "_val=\${$_req:-}"
if [ -z "$_val" ]; then
log_msg "[setup-import] Missing required field: ${_req} — falling through to wizard"
clawdie_setup_import_cleanup_mount
return 0
fi
done
step_done "wizard"
log_msg "[setup-import] Config loaded from $_part"
log_msg "[setup-import] HOSTNAME=${HOSTNAME:-<unset>} AGENT_DOMAIN=${AGENT_DOMAIN:-<unset>}"
log_msg "[setup-import] INSTALL_MODE=${INSTALL_MODE:-auto} → CLAWDIE_BOOT_MODE=${CLAWDIE_BOOT_MODE:-<auto-detect>}"
clawdie_setup_import_cleanup_mount
return 0
}
clawdie_setup_import_cleanup_mount() {
if [ "${_mounted:-0}" -eq 1 ]; then
umount "$CONFIG_MOUNT_POINT" 2>/dev/null || true
_mounted=0
fi
}
clawdie_setup_import_find_partition() {
for _candidate in \
"/dev/gpt/${CONFIG_LABEL}" \
"/dev/label/${CONFIG_LABEL}" \
"/dev/msdosfs/${CONFIG_LABEL}"
do
if [ -e "$_candidate" ]; then
echo "$_candidate"
return 0
fi
done
if command -v gpart >/dev/null 2>&1; then
gpart show -lp 2>/dev/null \
| awk -v label="$CONFIG_LABEL" '
$0 ~ label {
for (i = 1; i <= NF; i++) {
if ($i ~ "^/dev/") {
print $i;
exit;
}
}
}
'
return 0
fi
return 0
}
clawdie_setup_import_parse_file() {
_file="$1"
_kind="$2"
while IFS= read -r _line || [ -n "$_line" ]; do
_line=$(printf '%s' "$_line" | tr -d '\r')
case "$_line" in
''|'#'*) continue ;;
*=*) ;;
*) continue ;;
esac
_key=$(printf '%s' "$_line" | cut -d= -f1 | tr -d ' ')
_value=$(printf '%s' "$_line" | cut -d= -f2-)
_value=$(printf '%s' "$_value" | sed 's/^"//; s/"$//; s/^'\''//; s/'\''$//')
case "$_key" in
SETUP_SCHEMA_VERSION|ISO_RELEASE|ISO_GIT_COMMIT|INSTALL_MODE|ASSISTANT_NAME|AGENT_DOMAIN|PROFILE|TIMEZONE|HOSTNAME|ZFS_POOL|ZFS_LAYOUT|ZFS_DATA_DISKS|ZFS_HOT_SPARES|ZFS_PREFIX|OPERATOR_EMAIL|OPERATOR_PASSWORD|SSH_PUBLIC_KEY|SSH_AUTHORIZED_KEY|CLAWDIE_USER_PASSWORD|SYSTEM_LOCALE|KEYMAP|TAILSCALE_AUTHKEY)
eval "$_key=\$_value"
export "$_key"
;;
SYSTEM_SCHEMA_VERSION|NETWORK_EXTERNAL_IF|NETWORK_INTERNAL_IF|TAILSCALE_IF|ZFS_DISKS|ZFS_SPARE_DISKS|GPU_DEVICE|SND_DEVICE)
if [ "$_kind" = "system" ]; then
eval "$_key=\$_value"
export "$_key"
fi
;;
esac
done < "$_file"
}
clawdie_setup_import_apply_defaults() {
if [ -n "${TIMEZONE:-}" ] && [ -z "${TZ:-}" ]; then
TZ="$TIMEZONE"
fi
TZ="${TZ:-UTC}"
if [ -z "${HOSTNAME:-}" ] && [ -n "${ASSISTANT_NAME:-}" ]; then
HOSTNAME=$(printf '%s' "$ASSISTANT_NAME" | tr 'A-Z' 'a-z' | sed 's/[^a-z0-9]//g')
fi
HOSTNAME="${HOSTNAME:-clawdie}"
if [ -z "${AGENT_DOMAIN:-}" ]; then
AGENT_DOMAIN="${HOSTNAME}.home.arpa"
fi
SYSTEM_LOCALE="${SYSTEM_LOCALE:-en_US.UTF-8}"
DISPLAY_LOCALE="${DISPLAY_LOCALE:-$SYSTEM_LOCALE}"
ASSISTANT_LOCALE="${ASSISTANT_LOCALE:-$SYSTEM_LOCALE}"
KEYMAP="${KEYMAP:-us}"
if [ -n "${SSH_AUTHORIZED_KEY:-}" ] && [ -z "${SSH_PUBLIC_KEY:-}" ]; then
SSH_PUBLIC_KEY="$SSH_AUTHORIZED_KEY"
fi
if [ -n "${TAILSCALE_AUTHKEY:-}" ]; then
FEATURE_TAILSCALE="${FEATURE_TAILSCALE:-YES}"
fi
if [ -n "${ZFS_POOL:-}" ]; then
POOL_NAME="$ZFS_POOL"
fi
case "${INSTALL_MODE:-auto}" in
fresh)
CLAWDIE_BOOT_MODE="install"
CLAWDIE_BOOT_MODE_PRESET="1"
;;
upgrade)
CLAWDIE_BOOT_MODE="upgrade"
CLAWDIE_BOOT_MODE_PRESET="1"
;;
rescue)
CLAWDIE_BOOT_MODE="maintenance"
CLAWDIE_BOOT_MODE_PRESET="1"
;;
*)
;;
esac
export TZ HOSTNAME AGENT_DOMAIN SYSTEM_LOCALE DISPLAY_LOCALE ASSISTANT_LOCALE KEYMAP
export SSH_PUBLIC_KEY FEATURE_TAILSCALE
export POOL_NAME CLAWDIE_BOOT_MODE CLAWDIE_BOOT_MODE_PRESET
}
if ! command -v log_msg >/dev/null 2>&1; then
log_msg() { echo "$(date '+%H:%M:%S') $1" | tee -a "$LOG_FILE" 2>/dev/null || true; }
fi
if [ "${SETUP_IMPORT_TEST:-0}" -eq 0 ] && [ "$(basename "$0")" = "setup-import.sh" ]; then
clawdie_setup_import_load
fi