#!/bin/sh # Clawdie operator USB live seed importer. # Reads operator-provided files from the FAT32 CLAWDIESEED partition # (mountable on Linux pre-flash) and installs them into the live system # at every boot. Idempotent by design: editing the seed and rebooting # re-applies it. Failure is never fatal — missing/empty/unmountable seed # logs and continues so the operator can still log in via SDDM. # # Runs before LOGIN so sshd sees the imported authorized_keys on first # attach. See live/operator-session/clawdie-live-seed.README.txt for the # allowlisted file contract written to the FAT at build time. # PROVIDE: clawdie_live_seed # REQUIRE: FILESYSTEMS devfs # BEFORE: LOGIN # KEYWORD: nojail . /etc/rc.subr name="clawdie_live_seed" rcvar="${name}_enable" start_cmd="${name}_start" stop_cmd=":" # This service is one-shot/idempotent, not a daemon — the default # rc.subr status check looks for a pidfile and would say "not running" # even after a successful import, which is actively misleading. Override # with a log-tail report so `service clawdie_live_seed status` answers # the question the operator is actually asking ("did the import run?"). status_cmd="${name}_status" extra_commands="status" SEED_LABEL="CLAWDIESEED" SEED_MOUNT="/mnt/clawdie-seed" SEED_LOG="/var/log/clawdie-live-seed.log" SEED_USER="clawdie" SEED_USER_HOME="/home/clawdie" _seed_log() { printf '%s %s\n' "$(date '+%Y-%m-%dT%H:%M:%S')" "$1" >>"${SEED_LOG}" 2>/dev/null || true } _seed_find_partition() { for _candidate in \ "/dev/msdosfs/${SEED_LABEL}" \ "/dev/gpt/${SEED_LABEL}" \ "/dev/label/${SEED_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="${SEED_LABEL}" ' $0 ~ label { for (i = 1; i <= NF; i++) { if ($i ~ "^/dev/") { print $i; exit } } } ' fi return 0 } _seed_install_authorized_keys() { _src="$1" _ssh_dir="${SEED_USER_HOME}/.ssh" _dst="${_ssh_dir}/authorized_keys" mkdir -p "${_ssh_dir}" chown "${SEED_USER}:${SEED_USER}" "${_ssh_dir}" 2>/dev/null || true chmod 0700 "${_ssh_dir}" # Strip CRLF so keys created on Windows/Linux editors don't get rejected # by sshd for trailing whitespace. tr -d '\r' <"${_src}" >"${_dst}.new" mv -f "${_dst}.new" "${_dst}" chown "${SEED_USER}:${SEED_USER}" "${_dst}" 2>/dev/null || true chmod 0600 "${_dst}" _seed_log "installed authorized_keys from ${_src} -> ${_dst}" } clawdie_live_seed_start() { : >>"${SEED_LOG}" 2>/dev/null || true _dev=$(_seed_find_partition) if [ -z "${_dev:-}" ]; then _seed_log "no ${SEED_LABEL} partition found — skipping import" return 0 fi mkdir -p "${SEED_MOUNT}" if ! mount -t msdosfs -o ro "${_dev}" "${SEED_MOUNT}" 2>>"${SEED_LOG}"; then _seed_log "mount failed on ${_dev} — skipping import" return 0 fi # Allowlist: /ssh/authorized_keys takes precedence over /authorized_keys. # Any other file on the partition is ignored on purpose. _imported=0 if [ -f "${SEED_MOUNT}/ssh/authorized_keys" ]; then _seed_install_authorized_keys "${SEED_MOUNT}/ssh/authorized_keys" _imported=1 elif [ -f "${SEED_MOUNT}/authorized_keys" ]; then _seed_install_authorized_keys "${SEED_MOUNT}/authorized_keys" _imported=1 fi if [ "${_imported}" -eq 0 ]; then _seed_log "no allowlisted files on ${_dev} — nothing to import" fi umount "${SEED_MOUNT}" 2>/dev/null || true return 0 } clawdie_live_seed_status() { if [ -s "${SEED_LOG}" ]; then echo "${name}: one-shot importer; last run log tail:" tail -n 5 "${SEED_LOG}" return 0 fi echo "${name}: not yet run this boot (no log at ${SEED_LOG})" return 1 } load_rc_config "$name" : "${clawdie_live_seed_enable:=YES}" run_rc_command "$1"