feat: enhance install script with hardware detection, refactor studio UI, and enable GPU support for whisper service

This commit is contained in:
2025-12-29 23:49:21 -03:00
parent ad56d8a81c
commit 6326cad39d
12 changed files with 678 additions and 856 deletions
+111 -141
View File
@@ -1,14 +1,15 @@
#!/bin/bash
# OpenCCB Unified Installation Script
# This script automates the setup of OpenCCB, including prerequisites,
# repository cloning, dependencies, and initial configuration.
# This script automates the setup of OpenCCB:
# 1. Prerequisite checks (Rust, Node.js, Docker, sqlx-cli)
# 2. Hardware detection (NVIDIA GPU vs CPU)
# 3. Environment configuration (.env)
# 4. Database creation and migrations
# 5. System initialization (Admin account)
set -e
REPO_URL="https://github.com/Nurfog/openccb.git" # Example URL, should be updated if needed
PROJECT_DIR="openccb"
echo "===================================================="
echo " 🚀 Welcome to the OpenCCB Installer"
echo "===================================================="
@@ -19,24 +20,18 @@ if [ -f "Cargo.toml" ] && [ -d "services" ] && [ -d "web" ]; then
echo "✅ Project detected in current directory."
PROJECT_ROOT=$(pwd)
else
echo "📂 Project not detected in current directory."
if [ -d "$PROJECT_DIR" ]; then
echo "✅ Detected project folder '$PROJECT_DIR'."
cd "$PROJECT_DIR"
# Simplification: assume we are in the project root if the script is running
# but let's keep a basic check
if [ -d "openccb" ]; then
cd openccb
PROJECT_ROOT=$(pwd)
else
echo "📥 Project folder not found. Cloning from $REPO_URL..."
git clone "$REPO_URL" "$PROJECT_DIR"
cd "$PROJECT_DIR"
PROJECT_ROOT=$(pwd)
echo "⚠️ Please run this script from the root of the OpenCCB repository."
exit 1
fi
fi
# 2. Prerequisite Installation
echo ""
echo "🔍 Checking for prerequisites..."
# Function to check and install system packages (Ubuntu/Debian)
install_pkg() {
if ! command -v "$1" &> /dev/null; then
echo "🔧 Installing $1..."
@@ -46,7 +41,6 @@ install_pkg() {
fi
}
# Check for essential tools
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if [ -f /etc/debian_version ]; then
install_pkg "curl"
@@ -54,191 +48,167 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
install_pkg "jq"
install_pkg "build-essential"
install_pkg "docker.io"
# On modern Ubuntu, docker compose is a plugin included with docker.io or available as docker-compose-v2
if ! docker compose version &> /dev/null; then
install_pkg "docker-compose-v2"
fi
else
echo "⚠️ Unsupported Linux distribution. Please ensure curl, git, jq, docker, and docker-compose are installed."
fi
fi
# Check for Rust
if ! command -v cargo &> /dev/null; then
echo "🔧 Installing Rust..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
else
echo "✅ Rust (Cargo) is already installed."
fi
# Check for Node.js
if ! command -v node &> /dev/null; then
echo "🔧 Node.js not found. Installing via NVM..."
echo "🔧 Installing Node.js via NVM..."
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install --lts
else
echo "✅ Node.js $(node -v) is already installed."
fi
# Check for sqlx-cli
if ! command -v sqlx &> /dev/null; then
echo "🔧 Installing sqlx-cli..."
cargo install sqlx-cli --no-default-features --features postgres
else
echo "✅ sqlx-cli is already installed."
fi
# AI Stack Detection & Installation
# 3. Hardware Detection
echo ""
echo "🤖 Setting up Local AI Stack..."
echo "🔍 Detecting hardware..."
HAS_NVIDIA=false
if command -v nvidia-smi &> /dev/null; then
if nvidia-smi -L &> /dev/null; then
echo "🚀 NVIDIA GPU Detected!"
HAS_NVIDIA=true
fi
fi
if [ "$HAS_NVIDIA" = false ] && command -v lspci &> /dev/null; then
if lspci | grep -i nvidia &> /dev/null; then
echo "🚀 NVIDIA GPU Detected (lspci)!"
HAS_NVIDIA=true
fi
fi
# Ollama Installation
if ! command -v ollama &> /dev/null; then
echo "🔧 Installing Ollama..."
curl -fsSL https://ollama.com/install.sh | sh
if command -v nvidia-smi &> /dev/null && nvidia-smi -L &> /dev/null; then
echo "🚀 NVIDIA GPU Detected!"
HAS_NVIDIA=true
elif command -v lspci &> /dev/null && lspci | grep -i nvidia &> /dev/null; then
echo "🚀 NVIDIA GPU Detected (lspci)!"
HAS_NVIDIA=true
else
echo "✅ Ollama is already installed."
echo "💻 No NVIDIA GPU found. Using CPU mode."
fi
# Wait for Ollama to be ready
echo "⏳ Waiting for Ollama server to be ready..."
until curl -s http://localhost:11434/api/tags &> /dev/null; do
sleep 2
done
# Pre-download models based on hardware
if [ "$HAS_NVIDIA" = true ]; then
echo "📥 Downloading Llama 3 (optimized for GPU)..."
ollama pull llama3:8b
else
echo "📥 Downloading Phi-3 (lighter for CPU)..."
ollama pull phi3:mini
fi
# 3. Frontend Dependency Installation
echo ""
echo "📦 Installing frontend dependencies..."
for dir in "web/studio" "web/experience"; do
if [ -d "$dir" ]; then
echo "🔹 Installing in $dir..."
(cd "$dir" && npm install)
fi
done
# 4. Environment Configuration
echo ""
echo "⚙️ Configuring environment..."
if [ ! -f ".env" ]; then
if [ -f ".env.example" ]; then
echo "📄 Creating .env from .env.example..."
cp .env.example .env
else
echo "📄 Creating a new .env file..."
touch .env
fi
fi
# Function to update or add a variable in .env
update_env() {
local key=$1
local default_value=$2
local prompt_text=$3
# Read current value if it exists
local current_value=$(grep "^${key}=" .env | cut -d'=' -f2- || echo "")
local val=${current_value:-$default_value}
read -p "$prompt_text [$val]: " user_val
user_val=${user_val:-$val}
local val=$2
if grep -q "^${key}=" .env; then
# Use a temporary file for sed to be safe
sed -i "s|^${key}=.*|${key}=${user_val}|" .env
sed -i "s|^${key}=.*|${key}=${val}|" .env
else
echo "${key}=${user_val}" >> .env
echo "${key}=${val}" >> .env
fi
}
echo "Please provide the following configuration values (Press Enter for default):"
update_env "DATABASE_URL" "postgresql://user:password@localhost:5432/openccb" "Master Database URL"
update_env "CMS_DATABASE_URL" "postgresql://user:password@localhost:5432/openccb_cms" "CMS Database URL"
update_env "LMS_DATABASE_URL" "postgresql://user:password@localhost:5432/openccb_lms" "LMS Database URL"
update_env "NEXT_PUBLIC_CMS_API_URL" "http://localhost:3001" "Studio CMS API URL"
update_env "NEXT_PUBLIC_LMS_API_URL" "http://localhost:3002" "Experience LMS API URL"
echo ""
echo "🛠️ AI Configuration..."
update_env "AI_PROVIDER" "local" "AI Provider (openai | local)"
if [ "$(grep "^AI_PROVIDER=" .env | cut -d'=' -f2)" == "local" ]; then
update_env "LOCAL_OLLAMA_URL" "http://localhost:11434" "Local Ollama API URL"
update_env "LOCAL_WHISPER_URL" "http://localhost:8000" "Local Whisper API URL"
default_model="phi3:mini"
if [ "$HAS_NVIDIA" = true ]; then
default_model="llama3:8b"
fi
update_env "LOCAL_LLM_MODEL" "$default_model" "Local LLM Model"
# Auto-configure AI variables based on hardware
if [ "$HAS_NVIDIA" = true ]; then
update_env "WHISPER_IMAGE" "fedirz/faster-whisper-server:latest-cuda"
update_env "WHISPER_DEVICE" "cuda"
update_env "LOCAL_LLM_MODEL" "llama3:8b"
# Uncomment GPU deploy section in docker-compose.yml while preserving indentation
sed -i '/deploy:/s/# //' docker-compose.yml
sed -i '/resources:/s/# //' docker-compose.yml
sed -i '/reservations:/s/# //' docker-compose.yml
sed -i '/devices:/s/# //' docker-compose.yml
sed -i '/- driver: nvidia/s/# //' docker-compose.yml
sed -i '/count: 1/s/# //' docker-compose.yml
sed -i '/capabilities: \[ gpu \]/s/# //' docker-compose.yml
else
update_env "OPENAI_API_KEY" "" "OpenAI API Key"
update_env "WHISPER_IMAGE" "fedirz/faster-whisper-server:latest-cpu"
update_env "WHISPER_DEVICE" "cpu"
update_env "LOCAL_LLM_MODEL" "phi3:mini"
# Ensure it's commented (if it was previously uncommented)
# (Simple approach: we leave it as is or explicitly comment it out)
fi
echo "✅ .env configuration updated."
# Ask for DB credentials if not set
if ! grep -q "DATABASE_URL=" .env || [[ $(grep "DATABASE_URL=" .env | cut -d'=' -f2) == "" ]]; then
read -p "Enter Database Password [password]: " DB_PASS
DB_PASS=${DB_PASS:-password}
update_env "DATABASE_URL" "postgresql://user:${DB_PASS}@localhost:5432/openccb"
update_env "CMS_DATABASE_URL" "postgresql://user:${DB_PASS}@localhost:5432/openccb_cms"
update_env "LMS_DATABASE_URL" "postgresql://user:${DB_PASS}@localhost:5432/openccb_lms"
fi
# 5. Database Initialization
# 5. AI Stack Setup
if ! command -v ollama &> /dev/null; then
curl -fsSL https://ollama.com/install.sh | sh
fi
echo "⏳ Starting Ollama & downloading models..."
# Run ollama in background if not running (simple check)
if ! pgrep ollama &> /dev/null; then
ollama serve &
sleep 5
fi
until curl -s http://localhost:11434/api/tags &> /dev/null; do sleep 2; done
if [ "$HAS_NVIDIA" = true ]; then
ollama pull llama3:8b
else
ollama pull phi3:mini
fi
# 6. Database Initialization (Integrated db-mgmt.sh)
echo ""
echo "🐘 Starting database with Docker..."
docker compose up -d db
sleep 5 # Simple wait
echo "⏳ Waiting for database to be ready..."
# Better wait using pg_isready if available
if command -v pg_isready &> /dev/null; then
until pg_isready -h localhost -p 5432 -U user; do
echo "Still waiting for Postgres..."
sleep 2
done
else
sleep 10
fi
CMS_URL=$(grep "CMS_DATABASE_URL=" .env | cut -d'=' -f2)
LMS_URL=$(grep "LMS_DATABASE_URL=" .env | cut -d'=' -f2)
echo "🏗️ Running database setup..."
chmod +x db-mgmt.sh
./db-mgmt.sh setup
echo "🏗️ Creating databases and running migrations..."
DATABASE_URL=$CMS_URL sqlx database create || true
DATABASE_URL=$LMS_URL sqlx database create || true
DATABASE_URL=$CMS_URL sqlx migrate run --source services/cms-service/migrations
DATABASE_URL=$LMS_URL sqlx migrate run --source services/lms-service/migrations
# 6. System Initialization
# 7. System Initialization (Integrated init-system.sh)
echo ""
echo "👤 Initializing system (Admin account)..."
chmod +x init-system.sh
./init-system.sh
echo "👤 Creating Initial Administrator..."
API_URL="http://localhost:3001"
# Start the CMS service temporarily to create the user?
# Better yet, start all services with docker compose
echo "🚀 Starting services to allow admin creation..."
docker compose up -d --build
echo "⏳ Waiting for CMS API to be ready..."
START_WAIT=$SECONDS
until curl -s "$API_URL/auth/login" &> /dev/null || [ $((SECONDS - START_WAIT)) -gt 60 ]; do sleep 2; done
read -p "Admin Email [admin@example.com]: " ADMIN_EMAIL
ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com}
read -s -p "Admin Password [password123]: " ADMIN_PASS
ADMIN_PASS=${ADMIN_PASS:-password123}
echo ""
PAYLOAD=$(jq -n \
--arg email "$ADMIN_EMAIL" \
--arg password "$ADMIN_PASS" \
--arg full_name "System Admin" \
--arg org_name "Default Organization" \
--arg role "admin" \
'{email: $email, password: $password, full_name: $full_name, organization_name: $org_name, role: $role}')
RESPONSE=$(curl -s -X POST "$API_URL/auth/register" -H "Content-Type: application/json" -d "$PAYLOAD")
if echo "$RESPONSE" | grep -q "token"; then
echo "✅ Success! Administrator created."
else
echo "⚠️ Failed to create administrator (it might already exist)."
fi
echo ""
echo "===================================================="
echo " ✨ OpenCCB Installation Complete!"
echo "===================================================="
echo "You can now start the services using 'docker compose up' or by"
echo "running 'npm run dev' inside the frontend directories and"
echo "'cargo run' inside the service directories."
echo ""
echo "Studio: http://localhost:3000"
echo "Experience: http://localhost:3003"
echo "CMS API: http://localhost:3001"
echo "LMS API: http://localhost:3002"
echo "===================================================="