#!/usr/bin/env bash # ───────────────────────────────────────────── # Cezen AI Suite — Entry Level Installer # Usage: # sudo bash install.sh → Phase 1 (drivers + schedules reboot → Phase 2) # sudo bash install.sh --phase=2 → Phase 2 (all software, run after reboot) # ───────────────────────────────────────────── set -e TIER="entry" PHASE="1" SKIP_ROLES="" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ANSIBLE_DIR="$SCRIPT_DIR/ansible" # Load saved config (written by web setup UI before phase 1) [ -f /opt/cezen/install.conf ] && source /opt/cezen/install.conf for arg in "$@"; do case $arg in --tier=*) TIER="${arg#*=}" ;; --phase=*) PHASE="${arg#*=}" ;; --skip=*) SKIP_ROLES="${arg#*=}" ;; esac done # ── Preflight ────────────────────────────────── check_root() { if [ "$EUID" -ne 0 ]; then echo "ERROR: Run as root: sudo bash install.sh" exit 1 fi } check_os() { if [ -f /etc/os-release ]; then . /etc/os-release if [[ "$ID" != "ubuntu" ]]; then echo "ERROR: Ubuntu 22.04 required. Detected: $PRETTY_NAME" exit 1 fi echo "✓ OS: $PRETTY_NAME" fi } install_ansible() { if ! command -v ansible-playbook &>/dev/null; then echo "→ Installing Ansible..." apt-get update -qq apt-get install -y -qq ansible python3-pip fi echo "✓ Ansible ready" } # ── Phase 1: NVIDIA drivers only ────────────── run_phase1() { echo "" echo "╔══════════════════════════════════════════╗" echo "║ Cezen AI Suite — Phase 1: NVIDIA ║" echo "╚══════════════════════════════════════════╝" ANSIBLE_STDOUT_CALLBACK=yaml \ ansible-playbook -i localhost, -c local "$ANSIBLE_DIR/phase1_nvidia.yml" \ -e "tier=$TIER" # Register phase 2 as a one-shot systemd service so it runs after reboot cat > /etc/systemd/system/cezen-phase2.service << EOF [Unit] Description=Cezen AI Suite Phase 2 Installer After=network-online.target nvidia-persistenced.service Wants=network-online.target [Service] Type=oneshot ExecStart=/bin/bash ${SCRIPT_DIR}/install.sh --phase=2 --tier=${TIER} RemainAfterExit=yes StandardOutput=journal+console StandardError=journal+console [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable cezen-phase2.service echo "" echo "✓ Phase 2 registered — will run automatically after reboot" echo "→ Rebooting in 10 seconds..." sleep 10 reboot } # ── Phase 2: Full stack ──────────────────────── run_phase2() { echo "" echo "╔══════════════════════════════════════════╗" echo "║ Cezen AI Suite — Phase 2: Stack ║" echo "╚══════════════════════════════════════════╝" # Verify NVIDIA driver loaded if ! nvidia-smi &>/dev/null; then echo "WARNING: nvidia-smi not responding. NVIDIA driver may not be loaded." echo " Continuing — non-GPU roles will still install correctly." else echo "✓ NVIDIA driver: $(nvidia-smi --query-gpu=driver_version --format=csv,noheader | head -1)" fi # Build skip_roles extra var (comma-separated list, empty string = skip nothing) EXTRA_VARS="tier=$TIER skip_roles=\"$SKIP_ROLES\"" echo "→ Tier: $TIER | Skip: ${SKIP_ROLES:-none}" ANSIBLE_STDOUT_CALLBACK=yaml \ ansible-playbook -i localhost, -c local "$ANSIBLE_DIR/entry.yml" \ -e "$EXTRA_VARS" # Disable one-shot service so it doesn't run again on next reboot systemctl disable cezen-phase2.service 2>/dev/null || true echo "" echo "╔══════════════════════════════════════════╗" echo "║ Cezen AI Suite installation complete! ║" echo "║ ║" echo "║ JupyterLab → http://localhost:8888 ║" echo "║ Ollama API → http://localhost:11434 ║" echo "║ MLflow → http://localhost:5000 ║" echo "║ MinIO → http://localhost:9001 ║" echo "║ Grafana → http://localhost:3000 ║" echo "╚══════════════════════════════════════════╝" } # ── Main ─────────────────────────────────────── check_root check_os install_ansible if [ "$PHASE" = "1" ]; then run_phase1 elif [ "$PHASE" = "2" ]; then run_phase2 else echo "ERROR: Unknown phase '$PHASE'. Use --phase=1 or --phase=2" exit 1 fi