Add top-level checklist menu to laptop_full_setup.sh

Replace the single-choice component menu with a multi-select checklist
(whiptail if available, text-based toggle fallback). Users now pick any
combination of:

  [*] Full system setup  — runs ubuntu-post-install.sh (Ubuntu apps,
                           security hardening, backups, Docker services)
  [*] AI stack           — Ollama, Open WebUI, RAG, MCP, Gitea, InvokeAI
  [*] Kiwix              — Offline Wikipedia, Stack Overflow, Arch Wiki

This makes laptop_full_setup.sh the single entry point — run it once,
toggle what you need (like Ubuntu Server's tasksel), leave overnight.

https://claude.ai/code/session_012gDnantBmFTWZGCiKyjazx
This commit is contained in:
Claude
2026-03-20 22:03:49 +00:00
parent 92f5d886c7
commit 45dfa58d93
+80 -21
View File
@@ -1,14 +1,18 @@
#!/usr/bin/env bash
# =============================================================================
# Local AI Stack — Ubuntu 24.04
# Services: Ollama · Open WebUI · RAG · MCP · ChromaDB · SearXNG
# Kiwix · Gitea · InvokeAI · Portainer
# Local AI Setup — Ubuntu 24.04
# One script to rule them all. Select what you need, answer questions, walk away.
#
# Options (checklist at launch):
# • Full system setup — Ubuntu apps, security, backups (ubuntu-post-install.sh)
# • AI stack — Ollama · Open WebUI · RAG · MCP · ChromaDB · SearXNG
# Gitea · InvokeAI · Portainer
# • Kiwix — Offline Wikipedia, Stack Overflow, Arch Wiki, etc.
#
# Usage:
# ./laptop_full_setup.sh — interactive setup (answer questions, leave overnight)
# ./laptop_full_setup.sh — interactive (asks everything upfront)
# ./laptop_full_setup.sh --force — overwrite existing config files too
#
# Asks all questions upfront, then runs everything unattended.
# GPU: Ollama auto-detects VRAM — works with any NVIDIA GPU
# =============================================================================
set -euo pipefail
@@ -78,22 +82,60 @@ info "LAN IP : $LOCAL_IP"
info "GPU : ${GPU_NAME} (${VRAM_GB}GB VRAM)"
$IS_UPDATE && warn "Existing install found. Config files kept unless --force is passed."
# ── Q1: Components ────────────────────────────────────────────────────────────
echo ""
echo -e " ${BOLD}[1/5] What do you want to install?${NC}"
echo ""
echo " 1) Full stack — AI stack + Kiwix offline library"
echo " 2) AI stack — Ollama · WebUI · RAG · MCP · ChromaDB · SearXNG · Gitea · InvokeAI · Portainer"
echo " 3) Kiwix only — Offline Wikipedia / docs (runs standalone)"
echo ""
read -rp " Choice [1]: " MENU_CHOICE
MENU_CHOICE="${MENU_CHOICE:-1}"
case "$MENU_CHOICE" in
1) INSTALL_AI=true; INSTALL_KIWIX=true ;;
2) INSTALL_AI=true; INSTALL_KIWIX=false ;;
3) INSTALL_AI=false; INSTALL_KIWIX=true ;;
*) die "Invalid choice '$MENU_CHOICE' — run again and choose 1, 2, or 3" ;;
esac
# ── Q1: What to install — checklist ──────────────────────────────────────────
INSTALL_POSTINSTALL=false
INSTALL_AI=true
INSTALL_KIWIX=true
POSTINSTALL_SCRIPT="$SCRIPT_DIR/ubuntu-post-install.sh"
HAS_POSTINSTALL=false
[[ -f "$POSTINSTALL_SCRIPT" ]] && HAS_POSTINSTALL=true
# Build checklist via whiptail if available, else text toggle
if command -v whiptail &>/dev/null; then
WHIP_ARGS=()
$HAS_POSTINSTALL && WHIP_ARGS+=(
"postinstall" "Full system setup — Ubuntu apps, security, backups" OFF
)
WHIP_ARGS+=(
"aistack" "AI stack — Ollama · WebUI · RAG · MCP · Gitea · InvokeAI" ON
"kiwix" "Kiwix — Offline Wikipedia, Stack Overflow, Arch Wiki…" ON
)
SELECTED=$(whiptail --title "Local AI Setup" \
--checklist "SPACE = toggle TAB = move ENTER = confirm" \
15 72 "${#WHIP_ARGS[@]}" "${WHIP_ARGS[@]}" 3>&1 1>&2 2>&3) || die "Cancelled."
INSTALL_AI=false; INSTALL_KIWIX=false
[[ "$SELECTED" == *"postinstall"* ]] && INSTALL_POSTINSTALL=true
[[ "$SELECTED" == *"aistack"* ]] && INSTALL_AI=true
[[ "$SELECTED" == *"kiwix"* ]] && INSTALL_KIWIX=true
else
# Text-based toggle list
echo ""
echo -e " ${BOLD}[1/5] Select what to install${NC}"
echo " (Type a number to toggle on/off, then press Enter with no number to confirm)"
echo ""
SEL_POST=false; SEL_AI=true; SEL_KIWIX=true
while true; do
echo ""
$HAS_POSTINSTALL && printf " [%s] 1. Full system setup — Ubuntu apps, security, backups\n" "$($SEL_POST && echo '*' || echo ' ')"
printf " [%s] 2. AI stack — Ollama · WebUI · RAG · MCP · Gitea · InvokeAI\n" "$($SEL_AI && echo '*' || echo ' ')"
printf " [%s] 3. Kiwix — Offline Wikipedia, Stack Overflow, docs\n" "$($SEL_KIWIX && echo '*' || echo ' ')"
echo ""
read -rp " Toggle [number] or Enter to confirm: " T
case "$T" in
1) $HAS_POSTINSTALL && { $SEL_POST && SEL_POST=false || SEL_POST=true; } ;;
2) $SEL_AI && SEL_AI=false || SEL_AI=true ;;
3) $SEL_KIWIX && SEL_KIWIX=false || SEL_KIWIX=true ;;
"") break ;;
esac
done
INSTALL_POSTINSTALL=$SEL_POST
INSTALL_AI=$SEL_AI
INSTALL_KIWIX=$SEL_KIWIX
fi
$INSTALL_AI || $INSTALL_KIWIX || $INSTALL_POSTINSTALL \
|| die "Nothing selected — run again and select at least one option."
# ── Q2: Storage for Ollama models ─────────────────────────────────────────────
OLLAMA_STORAGE="volume" # "volume" = Docker named volume, else a host path
@@ -204,6 +246,7 @@ echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━
echo -e "${BOLD} Setup plan — starting now:${NC}"
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
$INSTALL_POSTINSTALL && echo " ✓ Full system setup (ubuntu-post-install.sh — interactive)"
$INSTALL_AI && echo " ✓ AI stack (Ollama · WebUI · RAG · MCP · Gitea · InvokeAI · Portainer)"
$INSTALL_KIWIX && echo " ✓ Kiwix offline library"
if $INSTALL_AI; then
@@ -235,6 +278,22 @@ write_if_new() {
fi
}
# =============================================================================
# Run full system post-install first (sets up Docker, security, base services)
# =============================================================================
if $INSTALL_POSTINSTALL; then
section "Full System Setup"
if [[ ! -f "$POSTINSTALL_SCRIPT" ]]; then
die "ubuntu-post-install.sh not found at $POSTINSTALL_SCRIPT"
fi
info "Launching ubuntu-post-install.sh in normal install mode..."
echo ""
bash "$POSTINSTALL_SCRIPT"
echo ""
ok "System setup complete — continuing with selected components..."
echo ""
fi
# =============================================================================
section "Prerequisites"
# =============================================================================