The box announces itself — publish path verified from 10.0.1.20 with a 200 on 2026-08-01. Never blocks or fails the bootstrap.
113 lines
4.6 KiB
Bash
Executable File
113 lines
4.6 KiB
Bash
Executable File
#!/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
|
|
|
|
# ---- announce the result on ntfy (best-effort, never blocks) ---------------------
|
|
# The box tells Mike's phone directly — publish path verified from 10.0.1.20
|
|
# (HTTP 200) on 2026-08-01. A notification failure must never fail the bootstrap.
|
|
NTFY_URL="https://ntfy.thewichersfamily.com/arrsstack-alerts"
|
|
MOUNTS_OK="$("$REPO_DIR/scripts/20-cifs.sh" --verify >/dev/null 2>&1 && echo yes || echo no)"
|
|
if [ ${#FAILED[@]} -eq 0 ]; then
|
|
NTFY_TITLE="mediabox: first boot COMPLETE"
|
|
NTFY_MSG="All bootstrap stages OK on $(hostname) ($(hostname -I | awk '{print $1}')). NAS mounts: ${MOUNTS_OK}. Next: message Claude 'box is up' to start the D: copy."
|
|
else
|
|
NTFY_TITLE="mediabox: first boot NEEDS ATTENTION"
|
|
NTFY_MSG="Stages failed: ${FAILED[*]}. NAS mounts: ${MOUNTS_OK}. SSH in (thethreemagi@10.0.1.20) or tell Claude which stage failed. Log: /var/log/mediabox-bootstrap.log"
|
|
fi
|
|
curl -s -m 10 -H "Title: ${NTFY_TITLE}" -d "${NTFY_MSG}" "$NTFY_URL" >/dev/null 2>&1 \
|
|
|| warn "ntfy notification failed (non-fatal)"
|
|
|
|
cat <<'NEXT'
|
|
|
|
--------------------------------------------------------------------------------
|
|
REMAINING STEPS — deliberately NOT automated (2026-07-31 flow)
|
|
--------------------------------------------------------------------------------
|
|
1. NAS credentials: the CIDATA stick copy of user-data now writes
|
|
/etc/cifs/korval.cred on first boot, so the mounts normally come up on
|
|
their own. If they did not, write the cred file by hand and verify:
|
|
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
|
|
The six library shares must REFUSE writes, media_pc must accept them.
|
|
|
|
2. Verify Quick Sync before anything Plex-related:
|
|
vainfo --display drm --device /dev/dri/renderD128
|
|
|
|
3. Copy EVERYTHING off D: to the NAS media_pc share, stage via the SSD,
|
|
format D: to ext4, then restore and remap:
|
|
/srv/mediabox-bootstrap/migration/README.md (sections M2, M3, M4)
|
|
Do NOT claim the server. The migration preserves its identity.
|
|
The 337 GB Media/ cache lives on /srv/data (the former D:), NOT the SSD.
|
|
|
|
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. Soak 1-2 weeks. Keep the NAS media_pc backup — pruning it later is a
|
|
deliberate decision, not a cleanup step.
|
|
--------------------------------------------------------------------------------
|
|
NEXT
|
|
|
|
exit 0
|