Add self-deploying setup scripts for all sub-projects (P1-P8)
- Root setup.sh orchestrator with per-phase dispatch (./setup.sh p1..p8 | all | status) - Makefile convenience targets (make infra, make llm, make status, etc.) - scripts/common.sh: shared bash library for OS detection, Docker helpers, service management (launchd/systemd), package install, env management - .env.example + .gitignore: shared config template and secret exclusions P1 (homeai-infra): full implementation - docker-compose.yml: Uptime Kuma, code-server, n8n - Note: Home Assistant, Portainer, Gitea are pre-existing instances - setup.sh: Docker install, homeai network, container health checks P2 (homeai-llm): full implementation - Ollama native install with CUDA/ROCm/Metal auto-detection - launchd plist (macOS) + systemd service (Linux) for auto-start - scripts/pull-models.sh: idempotent model puller from manifest - scripts/benchmark.sh: tokens/sec measurement per model - Open WebUI on port 3030 (avoids Gitea :3000 conflict) P3-P8: working stubs with prerequisite checks and TODO sections Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
140
setup.sh
Normal file
140
setup.sh
Normal file
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup.sh — HomeAI root orchestrator
|
||||
#
|
||||
# Usage:
|
||||
# ./setup.sh all # run all phases in order
|
||||
# ./setup.sh p1 # infra only
|
||||
# ./setup.sh p2 # llm only
|
||||
# ./setup.sh p1 p2 # multiple phases
|
||||
# ./setup.sh status # show service health
|
||||
#
|
||||
# Phases: p1=infra p2=llm p3=voice p4=agent p5=character
|
||||
# p6=esp32 p7=visual p8=images
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# shellcheck source=scripts/common.sh
|
||||
source "${REPO_DIR}/scripts/common.sh"
|
||||
|
||||
# ─── Phase definitions ─────────────────────────────────────────────────────────
|
||||
declare -A PHASE_NAME=(
|
||||
[p1]="homeai-infra (Docker stack)"
|
||||
[p2]="homeai-llm (Ollama + Open WebUI)"
|
||||
[p3]="homeai-voice (STT / TTS / Wyoming)"
|
||||
[p4]="homeai-agent (OpenClaw + skills + mem0)"
|
||||
[p5]="homeai-character (Character Manager UI)"
|
||||
[p6]="homeai-esp32 (ESPHome firmware)"
|
||||
[p7]="homeai-visual (VTube Studio bridge)"
|
||||
[p8]="homeai-images (ComfyUI workflows)"
|
||||
)
|
||||
|
||||
PHASE_ORDER=(p1 p2 p3 p4 p5 p6 p7 p8)
|
||||
|
||||
run_phase() {
|
||||
local phase="$1"
|
||||
local subdir="${REPO_DIR}/homeai-${phase#p}"
|
||||
|
||||
# Map phase ID to directory name
|
||||
case "$phase" in
|
||||
p1) subdir="${REPO_DIR}/homeai-infra" ;;
|
||||
p2) subdir="${REPO_DIR}/homeai-llm" ;;
|
||||
p3) subdir="${REPO_DIR}/homeai-voice" ;;
|
||||
p4) subdir="${REPO_DIR}/homeai-agent" ;;
|
||||
p5) subdir="${REPO_DIR}/homeai-character" ;;
|
||||
p6) subdir="${REPO_DIR}/homeai-esp32" ;;
|
||||
p7) subdir="${REPO_DIR}/homeai-visual" ;;
|
||||
p8) subdir="${REPO_DIR}/homeai-images" ;;
|
||||
*) die "Unknown phase: $phase" ;;
|
||||
esac
|
||||
|
||||
local setup_script="${subdir}/setup.sh"
|
||||
if [[ ! -f "$setup_script" ]]; then
|
||||
die "Setup script not found: $setup_script"
|
||||
fi
|
||||
|
||||
log_section "Phase ${phase^^}: ${PHASE_NAME[$phase]}"
|
||||
bash "$setup_script"
|
||||
}
|
||||
|
||||
show_status() {
|
||||
log_section "HomeAI Service Status"
|
||||
|
||||
load_env_services
|
||||
|
||||
local services=(
|
||||
"Home Assistant|${HA_URL:-http://localhost:8123}"
|
||||
"Portainer|${PORTAINER_URL:-https://localhost:9443}"
|
||||
"Uptime Kuma|${UPTIME_KUMA_URL:-http://localhost:3001}"
|
||||
"Gitea|${GITEA_URL:-http://localhost:3000}"
|
||||
"code-server|${CODE_SERVER_URL:-http://localhost:8090}"
|
||||
"n8n|${N8N_URL:-http://localhost:5678}"
|
||||
"Ollama|${OLLAMA_URL:-http://localhost:11434}"
|
||||
"Open WebUI|${OPEN_WEBUI_URL:-http://localhost:3030}"
|
||||
)
|
||||
|
||||
for entry in "${services[@]}"; do
|
||||
local name="${entry%%|*}"
|
||||
local url="${entry##*|}"
|
||||
if curl -sf --max-time 2 "$url" -o /dev/null 2>/dev/null; then
|
||||
printf " ${GREEN}●${RESET} %-20s %s\n" "$name" "$url"
|
||||
else
|
||||
printf " ${RED}○${RESET} %-20s %s\n" "$name" "$url"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo ""
|
||||
echo " Usage: $0 <phase...> | all | status"
|
||||
echo ""
|
||||
echo " Phases:"
|
||||
for p in "${PHASE_ORDER[@]}"; do
|
||||
printf " %-6s %s\n" "$p" "${PHASE_NAME[$p]}"
|
||||
done
|
||||
echo ""
|
||||
echo " Examples:"
|
||||
echo " $0 all # setup everything in order"
|
||||
echo " $0 p1 p2 # infra + llm only"
|
||||
echo " $0 status # check service health"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ─── Main ──────────────────────────────────────────────────────────────────────
|
||||
main() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
detect_platform
|
||||
|
||||
# Bootstrap root .env if missing
|
||||
bootstrap_env "${REPO_DIR}"
|
||||
|
||||
local phases=()
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
all) phases=("${PHASE_ORDER[@]}") ;;
|
||||
status) show_status; exit 0 ;;
|
||||
p[1-8]) phases+=("$arg") ;;
|
||||
help|-h|--help) usage; exit 0 ;;
|
||||
*) die "Unknown argument: $arg. Run '$0 help' for usage." ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ${#phases[@]} -eq 0 ]]; then
|
||||
usage; exit 0
|
||||
fi
|
||||
|
||||
for phase in "${phases[@]}"; do
|
||||
run_phase "$phase"
|
||||
done
|
||||
|
||||
log_section "Setup complete"
|
||||
show_status
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user