#!/usr/bin/env bash # ============================================================================= # mediabox-bootstrap — first-boot orchestrator # # Runs ONCE from mediabox-firstboot.service, but every stage is idempotent so # you can re-run this by hand at any time: # sudo /srv/mediabox-bootstrap/bootstrap.sh # # Or run a single stage: # sudo /srv/mediabox-bootstrap/scripts/20-cifs.sh # # DESIGN RULE: no stage may leave the box unbootable or unreachable. Every # stage that can fail, fails soft and logs. sshd is already up by the time # this runs; keeping it that way is the whole safety net on a headless box. # ============================================================================= set -uo pipefail REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" STATE_DIR="/var/lib/mediabox" LOG="/var/log/mediabox-bootstrap.log" mkdir -p "$STATE_DIR" exec > >(tee -a "$LOG") 2>&1 say() { printf '\n\033[1;36m=== %s\033[0m\n' "$*"; } ok() { printf '\033[1;32m [ok]\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m [warn]\033[0m %s\n' "$*"; } fail() { printf '\033[1;31m [FAIL]\033[0m %s\n' "$*"; } [ "$(id -u)" -eq 0 ] || { fail "must run as root"; exit 1; } FAILED=() run_stage() { local script="$1" name name="$(basename "$script")" say "$name" if [ ! -x "$script" ]; then chmod +x "$script" 2>/dev/null || true; fi if "$script"; then ok "$name complete" else fail "$name exited $? — continuing (see $LOG)" FAILED+=("$name") fi } say "mediabox bootstrap starting $(date -Is)" echo "host: $(hostname) kernel: $(uname -r) ip: $(hostname -I)" run_stage "$REPO_DIR/scripts/00-preflight.sh" run_stage "$REPO_DIR/scripts/10-secrets.sh" run_stage "$REPO_DIR/scripts/20-cifs.sh" run_stage "$REPO_DIR/scripts/30-nvidia.sh" run_stage "$REPO_DIR/scripts/40-shell-mcp.sh" say "bootstrap summary" if [ ${#FAILED[@]} -eq 0 ]; then ok "all stages completed" touch "$STATE_DIR/firstboot.done" else warn "stages needing attention: ${FAILED[*]}" warn "NOT marking first-boot done — fix and re-run $0" fi cat <<'NEXT' -------------------------------------------------------------------------- REMAINING STEPS — deliberately NOT automated -------------------------------------------------------------------------- 1. Write the NAS password into the credentials file (over the MCP, never onto the USB): printf 'username=<nas-user>\npassword=<nas-pass>\ndomain=WORKGROUP\n' \ > /etc/cifs/korval.cred chmod 600 /etc/cifs/korval.cred systemctl daemon-reload /srv/mediabox-bootstrap/scripts/20-cifs.sh --verify 2. Verify Quick Sync before deploying Plex: vainfo --display drm --device /dev/dri/renderD128 3. Deploy Plex. PLEX_CLAIM expires in 4 minutes, so this is human-in-the-loop: # get a fresh token from https://plex.tv/claim THEN immediately: PLEX_CLAIM=claim-xxxxx /srv/mediabox-bootstrap/scripts/50-plex.sh 4. Repoint NPM proxy host 42 from mediabox-mcp:8103 to 10.0.1.20:8103, then delete the mediabox-mcp container and its key on arrsstack. 5. Leave D: alone until the soak is done. -------------------------------------------------------------------------- NEXT exit 0