713 lines
24 KiB
Bash
Executable File
713 lines
24 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# =============================================================================
|
||
# Media Manager - First-Time Setup Script
|
||
# =============================================================================
|
||
# This script guides you through the initial setup of the Media Manager
|
||
# application, including environment configuration and database initialization.
|
||
# =============================================================================
|
||
|
||
set -e
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
BOLD='\033[1m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Helper functions
|
||
print_header() {
|
||
echo ""
|
||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
echo -e "${BOLD}${CYAN} $1${NC}"
|
||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
echo ""
|
||
}
|
||
|
||
print_step() {
|
||
echo -e "${GREEN}▶${NC} $1"
|
||
}
|
||
|
||
print_info() {
|
||
echo -e "${CYAN}ℹ${NC} $1"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠${NC} $1"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}✗${NC} $1"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✓${NC} $1"
|
||
}
|
||
|
||
prompt_with_default() {
|
||
local prompt="$1"
|
||
local default="$2"
|
||
local var_name="$3"
|
||
local is_password="$4"
|
||
|
||
if [ "$is_password" = "true" ]; then
|
||
echo -en "${CYAN}?${NC} ${prompt} [${default}]: "
|
||
read -s value
|
||
echo ""
|
||
else
|
||
echo -en "${CYAN}?${NC} ${prompt} [${default}]: "
|
||
read value
|
||
fi
|
||
|
||
if [ -z "$value" ]; then
|
||
eval "$var_name=\"$default\""
|
||
else
|
||
eval "$var_name=\"$value\""
|
||
fi
|
||
}
|
||
|
||
prompt_yes_no() {
|
||
local prompt="$1"
|
||
local default="$2"
|
||
|
||
if [ "$default" = "y" ]; then
|
||
echo -en "${CYAN}?${NC} ${prompt} [Y/n]: "
|
||
else
|
||
echo -en "${CYAN}?${NC} ${prompt} [y/N]: "
|
||
fi
|
||
|
||
read answer
|
||
answer=${answer:-$default}
|
||
|
||
case "$answer" in
|
||
[Yy]* ) return 0;;
|
||
* ) return 1;;
|
||
esac
|
||
}
|
||
|
||
wait_for_container() {
|
||
local container="$1"
|
||
local max_attempts="${2:-30}"
|
||
local attempt=1
|
||
|
||
echo -n " Waiting for $container"
|
||
while [ $attempt -le $max_attempts ]; do
|
||
if docker compose ps "$container" 2>/dev/null | grep -q "healthy\|running"; then
|
||
echo -e " ${GREEN}ready${NC}"
|
||
return 0
|
||
fi
|
||
echo -n "."
|
||
sleep 2
|
||
attempt=$((attempt + 1))
|
||
done
|
||
|
||
echo -e " ${RED}timeout${NC}"
|
||
return 1
|
||
}
|
||
|
||
wait_for_postgres() {
|
||
local max_attempts="${1:-30}"
|
||
local attempt=1
|
||
|
||
echo -n " Waiting for PostgreSQL to be healthy"
|
||
while [ $attempt -le $max_attempts ]; do
|
||
if docker compose exec -T postgres pg_isready -U mediamanager -d library >/dev/null 2>&1; then
|
||
echo -e " ${GREEN}ready${NC}"
|
||
return 0
|
||
fi
|
||
echo -n "."
|
||
sleep 2
|
||
attempt=$((attempt + 1))
|
||
done
|
||
|
||
echo -e " ${RED}timeout${NC}"
|
||
return 1
|
||
}
|
||
|
||
wait_for_api() {
|
||
local max_attempts="${1:-30}"
|
||
local attempt=1
|
||
|
||
echo -n " Waiting for API to be healthy"
|
||
while [ $attempt -le $max_attempts ]; do
|
||
if curl -s http://localhost:3001/health >/dev/null 2>&1; then
|
||
echo -e " ${GREEN}ready${NC}"
|
||
return 0
|
||
fi
|
||
echo -n "."
|
||
sleep 2
|
||
attempt=$((attempt + 1))
|
||
done
|
||
|
||
echo -e " ${RED}timeout${NC}"
|
||
return 1
|
||
}
|
||
|
||
# =============================================================================
|
||
# Main Script
|
||
# =============================================================================
|
||
|
||
clear
|
||
echo ""
|
||
echo -e "${BOLD}${CYAN}"
|
||
echo " ╔══════════════════════════════════════════════════════════════════╗"
|
||
echo " ║ ║"
|
||
echo " ║ Media Manager - First-Time Setup ║"
|
||
echo " ║ ║"
|
||
echo " ╚══════════════════════════════════════════════════════════════════╝"
|
||
echo -e "${NC}"
|
||
echo ""
|
||
echo " This script will guide you through the initial setup process."
|
||
echo " Press Ctrl+C at any time to cancel."
|
||
echo ""
|
||
|
||
# =============================================================================
|
||
# Prerequisites Check
|
||
# =============================================================================
|
||
|
||
print_header "Checking Prerequisites"
|
||
|
||
# Check Docker
|
||
if command -v docker &> /dev/null; then
|
||
DOCKER_VERSION=$(docker --version | cut -d' ' -f3 | tr -d ',')
|
||
print_success "Docker installed (v$DOCKER_VERSION)"
|
||
else
|
||
print_error "Docker is not installed"
|
||
echo " Please install Docker: https://docs.docker.com/get-docker/"
|
||
exit 1
|
||
fi
|
||
|
||
# Check Docker Compose
|
||
if docker compose version &> /dev/null; then
|
||
COMPOSE_VERSION=$(docker compose version --short)
|
||
print_success "Docker Compose installed (v$COMPOSE_VERSION)"
|
||
else
|
||
print_error "Docker Compose is not installed"
|
||
echo " Please install Docker Compose: https://docs.docker.com/compose/install/"
|
||
exit 1
|
||
fi
|
||
|
||
# Check if Docker daemon is running
|
||
if docker info &> /dev/null; then
|
||
print_success "Docker daemon is running"
|
||
else
|
||
print_error "Docker daemon is not running"
|
||
echo " Please start Docker and try again"
|
||
exit 1
|
||
fi
|
||
|
||
# Check for NVIDIA GPU (optional)
|
||
if command -v nvidia-smi &> /dev/null; then
|
||
if nvidia-smi &> /dev/null; then
|
||
GPU_NAME=$(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | head -n1)
|
||
print_success "NVIDIA GPU detected: $GPU_NAME"
|
||
HAS_GPU=true
|
||
else
|
||
print_warning "NVIDIA driver not responding"
|
||
HAS_GPU=false
|
||
fi
|
||
else
|
||
print_info "No NVIDIA GPU detected (optional - CPU encoding will be used)"
|
||
HAS_GPU=false
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Check Existing Configuration
|
||
# =============================================================================
|
||
|
||
if [ -f ".env" ]; then
|
||
echo ""
|
||
print_warning "An existing .env file was found"
|
||
if prompt_yes_no "Do you want to overwrite it?" "n"; then
|
||
print_info "Backing up existing .env to .env.backup"
|
||
cp .env .env.backup
|
||
else
|
||
print_info "Keeping existing .env file"
|
||
SKIP_ENV_CREATION=true
|
||
fi
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Environment Configuration
|
||
# =============================================================================
|
||
|
||
if [ "$SKIP_ENV_CREATION" != "true" ]; then
|
||
|
||
print_header "Required Configuration"
|
||
|
||
# Generate JWT secret
|
||
JWT_SECRET=$(openssl rand -hex 32 2>/dev/null || cat /dev/urandom | tr -dc 'a-f0-9' | fold -w 64 | head -n 1)
|
||
print_info "Generated secure JWT secret"
|
||
|
||
# Generate PostgreSQL password
|
||
POSTGRES_PASSWORD=$(openssl rand -base64 24 2>/dev/null || cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
|
||
print_info "Generated secure PostgreSQL password"
|
||
|
||
echo ""
|
||
echo " Enter the initial admin account credentials."
|
||
echo " You will use these to log into the admin dashboard."
|
||
echo ""
|
||
|
||
prompt_with_default "Admin email" "admin@localhost" ADMIN_EMAIL
|
||
prompt_with_default "Admin password" "changeme" ADMIN_PASSWORD "true"
|
||
|
||
# =============================================================================
|
||
# Media Paths
|
||
# =============================================================================
|
||
|
||
print_header "Media Library Paths"
|
||
|
||
echo " Configure where your media files are stored."
|
||
echo " Use absolute paths. Leave blank to use defaults."
|
||
echo ""
|
||
|
||
# Try to detect current directory structure
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
DEFAULT_MEDIA_ROOT="$(dirname "$SCRIPT_DIR")/media"
|
||
|
||
prompt_with_default "Media root directory" "$DEFAULT_MEDIA_ROOT" MEDIA_ROOT
|
||
prompt_with_default "Local media directory" "$MEDIA_ROOT/local" MEDIA_LOCAL
|
||
prompt_with_default "Public media directory" "$MEDIA_ROOT/public" MEDIA_PUBLIC
|
||
prompt_with_default "Studios directory" "$MEDIA_LOCAL/studios" STUDIOS_PATH
|
||
prompt_with_default "GIFs directory" "$MEDIA_LOCAL/gifs" GIFS_PATH
|
||
prompt_with_default "Playback output directory" "$MEDIA_PUBLIC/playback" PLAYBACK_PATH
|
||
prompt_with_default "Compilations directory" "$MEDIA_PUBLIC/compilations" COMPILATIONS_PATH
|
||
prompt_with_default "Curated content directory" "$MEDIA_PUBLIC/curated" PUBLIC_CURATED_PATH
|
||
|
||
# =============================================================================
|
||
# Optional: SMTP Configuration
|
||
# =============================================================================
|
||
|
||
print_header "Email Configuration (Optional)"
|
||
|
||
echo " Email is used for user verification and password reset."
|
||
echo " Skip this section to use admin-approval workflow instead."
|
||
echo ""
|
||
|
||
if prompt_yes_no "Configure SMTP email?" "n"; then
|
||
prompt_with_default "SMTP host" "smtp.gmail.com" SMTP_HOST
|
||
prompt_with_default "SMTP port" "587" SMTP_PORT
|
||
prompt_with_default "SMTP username" "" SMTP_USER
|
||
prompt_with_default "SMTP password" "" SMTP_PASS "true"
|
||
prompt_with_default "From email address" "noreply@localhost" SMTP_FROM
|
||
prompt_with_default "From name" "Media Manager" SMTP_FROM_NAME
|
||
SMTP_SECURE="false"
|
||
else
|
||
SMTP_HOST=""
|
||
SMTP_PORT=""
|
||
SMTP_USER=""
|
||
SMTP_PASS=""
|
||
SMTP_FROM=""
|
||
SMTP_FROM_NAME=""
|
||
SMTP_SECURE=""
|
||
print_info "Skipping SMTP configuration"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Optional: AI Features
|
||
# =============================================================================
|
||
|
||
print_header "AI Features Configuration"
|
||
|
||
if [ "$HAS_GPU" = "true" ]; then
|
||
echo " All AI services will start automatically with the application."
|
||
echo " These use your NVIDIA GPU for accelerated processing."
|
||
echo ""
|
||
echo " Services included:"
|
||
echo " - Ollama (vision + text models for video analysis)"
|
||
echo " - Whisper (speech transcription)"
|
||
echo " - JoyCaption (high-quality image captioning)"
|
||
echo " - Face Recognition (performer detection)"
|
||
echo " - YOLO Detection (person counting)"
|
||
echo " - JoyTag (visual tagging)"
|
||
echo ""
|
||
|
||
# Content Safety
|
||
echo -e " ${BOLD}Content Safety Moderation${NC}"
|
||
echo " AI-powered comment moderation using Llama Guard."
|
||
echo " Screens user comments for harmful content."
|
||
echo ""
|
||
|
||
if prompt_yes_no "Enable content safety moderation?" "y"; then
|
||
SAFETY_CHECK_ENABLED="true"
|
||
print_info "Content safety will be enabled"
|
||
else
|
||
SAFETY_CHECK_ENABLED="false"
|
||
print_info "Content safety disabled (can be enabled later in .env)"
|
||
fi
|
||
|
||
# JoyCaption model check
|
||
echo ""
|
||
echo -e " ${BOLD}JoyCaption Vision Backend${NC}"
|
||
echo " Higher quality image captioning using JoyCaption GGUF model."
|
||
echo " Requires model files in ./models directory (~4.6GB download)"
|
||
echo ""
|
||
|
||
if prompt_yes_no "Will you download JoyCaption model files?" "y"; then
|
||
DIGEST_VISION_BACKEND="llama-server"
|
||
print_info "JoyCaption will be the primary vision backend"
|
||
print_warning "Download model files to ./models/ before using"
|
||
echo " Download from: https://huggingface.co/Mungert/llama-joycaption-beta-one-hf-llava-GGUF"
|
||
else
|
||
DIGEST_VISION_BACKEND="ollama"
|
||
print_info "Using Ollama for vision (default)"
|
||
fi
|
||
else
|
||
echo " AI features require an NVIDIA GPU."
|
||
echo " AI services will start but may not function properly without GPU."
|
||
echo ""
|
||
SAFETY_CHECK_ENABLED="false"
|
||
DIGEST_VISION_BACKEND="ollama"
|
||
print_warning "No GPU detected - AI features may be limited"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Application Settings
|
||
# =============================================================================
|
||
|
||
print_header "Application Settings"
|
||
|
||
prompt_with_default "Public gallery URL" "http://localhost:3080" APP_BASE_URL
|
||
prompt_with_default "Timezone" "UTC" TZ
|
||
|
||
# =============================================================================
|
||
# Generate .env File
|
||
# =============================================================================
|
||
|
||
print_header "Generating Configuration"
|
||
|
||
print_step "Creating .env file..."
|
||
|
||
cat > .env << EOF
|
||
# =============================================================================
|
||
# Media Manager Configuration
|
||
# Generated by build.sh on $(date)
|
||
# =============================================================================
|
||
|
||
# PostgreSQL Database (REQUIRED)
|
||
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
|
||
|
||
# JWT Authentication
|
||
JWT_SECRET=$JWT_SECRET
|
||
|
||
# Initial Admin Account
|
||
INITIAL_ADMIN_EMAIL=$ADMIN_EMAIL
|
||
INITIAL_ADMIN_PASSWORD=$ADMIN_PASSWORD
|
||
|
||
# SMTP Configuration
|
||
SMTP_HOST=$SMTP_HOST
|
||
SMTP_PORT=$SMTP_PORT
|
||
SMTP_SECURE=${SMTP_SECURE:-false}
|
||
SMTP_USER=$SMTP_USER
|
||
SMTP_PASS=$SMTP_PASS
|
||
SMTP_FROM=$SMTP_FROM
|
||
SMTP_FROM_NAME=$SMTP_FROM_NAME
|
||
|
||
# Email Settings
|
||
EMAIL_VERIFICATION_EXPIRY_HOURS=24
|
||
PASSWORD_RESET_EXPIRY_HOURS=1
|
||
|
||
# Application Settings
|
||
APP_BASE_URL=$APP_BASE_URL
|
||
ALLOWED_ORIGINS=http://localhost:3080,http://localhost:8080
|
||
TZ=$TZ
|
||
VITE_DEFAULT_LOCALE=
|
||
|
||
# Content Safety
|
||
SAFETY_CHECK_ENABLED=$SAFETY_CHECK_ENABLED
|
||
OLLAMA_BASE_URL=http://ollama:11434
|
||
OLLAMA_MODEL=llama-guard3:1b
|
||
|
||
# Digest Feature Models (for AI video analysis)
|
||
DIGEST_VISION_MODEL=huihui_ai/qwen3-vl-abliterated:2b
|
||
DIGEST_TEXT_MODEL=huihui_ai/qwen3-abliterated:4b
|
||
DIGEST_OLLAMA_URL=http://ollama:11434
|
||
DIGEST_WHISPER_URL=http://whisper:5000
|
||
DIGEST_FRAME_INTERVAL=30
|
||
|
||
# JoyCaption (alternative vision backend)
|
||
DIGEST_VISION_BACKEND=$DIGEST_VISION_BACKEND
|
||
JOYCAPTION_URL=http://joycaption:8080
|
||
JOYCAPTION_MODEL=llama-joycaption-beta-one-hf-llava
|
||
JOYCAPTION_FALLBACK_TO_OLLAMA=true
|
||
JOYCAPTION_MODEL_PATH=/models/llama-joycaption-beta-one-hf-llava.Q2_K.gguf
|
||
JOYCAPTION_MMPROJ_PATH=/models/llama-joycaption-beta-one-llava-mmproj-model-f16.gguf
|
||
JOYCAPTION_CTX_SIZE=4096
|
||
JOYCAPTION_GPU_LAYERS=999
|
||
JOYCAPTION_PARALLEL=1
|
||
|
||
# Whisper Transcription
|
||
WHISPER_MODEL=base
|
||
WHISPER_DEVICE=cuda
|
||
WHISPER_COMPUTE=float16
|
||
|
||
# Ollama Auto-Pull Models
|
||
OLLAMA_MODELS=llama-guard3:1b,huihui_ai/qwen3-vl-abliterated:2b,huihui_ai/qwen3-abliterated:4b
|
||
|
||
# Media Library Paths
|
||
MEDIA_ROOT=$MEDIA_ROOT
|
||
MEDIA_LOCAL=$MEDIA_LOCAL
|
||
MEDIA_PUBLIC=$MEDIA_PUBLIC
|
||
STUDIOS_PATH=$STUDIOS_PATH
|
||
ONLYFANS_PATH=$MEDIA_LOCAL/OnlyFans
|
||
GIFS_PATH=$GIFS_PATH
|
||
PLAYBACK_PATH=$PLAYBACK_PATH
|
||
COMPILATIONS_PATH=$COMPILATIONS_PATH
|
||
PUBLIC_CURATED_PATH=$PUBLIC_CURATED_PATH
|
||
QUICKIES_PATH=$MEDIA_PUBLIC/quickies
|
||
EOF
|
||
|
||
print_success ".env file created"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Create Docker Network
|
||
# =============================================================================
|
||
|
||
print_header "Setting Up Docker"
|
||
|
||
print_step "Checking Docker network..."
|
||
|
||
if docker network inspect media-network &> /dev/null; then
|
||
print_success "Docker network 'media-network' already exists"
|
||
else
|
||
print_step "Creating Docker network 'media-network'..."
|
||
docker network create media-network
|
||
print_success "Docker network created"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Create Required Directories
|
||
# =============================================================================
|
||
|
||
print_step "Creating data directories..."
|
||
|
||
mkdir -p data/thumbnails
|
||
mkdir -p data/digest_frames
|
||
mkdir -p data/ads
|
||
mkdir -p data/gallery
|
||
mkdir -p models
|
||
|
||
print_success "Data directories created"
|
||
|
||
# =============================================================================
|
||
# Start Services
|
||
# =============================================================================
|
||
|
||
print_header "Starting Services"
|
||
|
||
print_step "Pulling Docker images (this may take a while)..."
|
||
|
||
docker compose pull
|
||
|
||
# Check for JoyCaption model files
|
||
print_step "Checking JoyCaption model files..."
|
||
if [ -f "models/llama-joycaption-beta-one-hf-llava-Q3_K_M.gguf" ] && \
|
||
[ -f "models/llama-joycaption-beta-one-llava-mmproj-model-f16.gguf" ]; then
|
||
print_success "JoyCaption model files found"
|
||
else
|
||
print_warning "JoyCaption model files not found in ./models/"
|
||
echo ""
|
||
echo " Download these files to enable JoyCaption vision backend:"
|
||
echo " 1. llama-joycaption-beta-one-hf-llava-Q3_K_M.gguf (~4GB)"
|
||
echo " 2. llama-joycaption-beta-one-llava-mmproj-model-f16.gguf (~600MB)"
|
||
echo ""
|
||
echo " From: https://huggingface.co/Mungert/llama-joycaption-beta-one-hf-llava-GGUF"
|
||
echo ""
|
||
print_info "JoyCaption container will start but won't work until models are downloaded"
|
||
fi
|
||
|
||
print_step "Starting containers..."
|
||
|
||
# Start core services first
|
||
docker compose up -d
|
||
|
||
# Ask about AI services
|
||
echo ""
|
||
if [ "$HAS_GPU" = "true" ]; then
|
||
if prompt_yes_no "Start AI services now? (can be started later with: docker compose --profile ai up -d)" "y"; then
|
||
print_step "Starting AI services..."
|
||
docker compose --profile ai up -d
|
||
START_AI_SERVICES=true
|
||
else
|
||
START_AI_SERVICES=false
|
||
print_info "AI services not started. Start later with: docker compose --profile ai up -d"
|
||
fi
|
||
else
|
||
START_AI_SERVICES=false
|
||
print_info "Skipping AI services (no GPU detected)"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Wait for Services
|
||
# =============================================================================
|
||
|
||
print_header "Waiting for Services"
|
||
|
||
print_step "Checking service health..."
|
||
|
||
if ! wait_for_postgres 60; then
|
||
print_error "PostgreSQL failed to start"
|
||
echo ""
|
||
echo " Check the logs with: docker compose logs postgres"
|
||
exit 1
|
||
fi
|
||
|
||
# Wait for Ollama to start and pull models (only if AI services were started)
|
||
if [ "$START_AI_SERVICES" = "true" ]; then
|
||
print_step "Waiting for Ollama to start and pull models..."
|
||
echo " (This may take several minutes on first run as models are downloaded)"
|
||
echo ""
|
||
|
||
# Wait for Ollama to be responsive (not necessarily fully ready with models)
|
||
MAX_OLLAMA_WAIT=30
|
||
OLLAMA_ATTEMPT=1
|
||
echo -n " Waiting for Ollama"
|
||
while [ $OLLAMA_ATTEMPT -le $MAX_OLLAMA_WAIT ]; do
|
||
if curl -s http://localhost:11435/ >/dev/null 2>&1; then
|
||
echo -e " ${GREEN}ready${NC}"
|
||
break
|
||
fi
|
||
echo -n "."
|
||
sleep 2
|
||
OLLAMA_ATTEMPT=$((OLLAMA_ATTEMPT + 1))
|
||
done
|
||
|
||
if [ $OLLAMA_ATTEMPT -gt $MAX_OLLAMA_WAIT ]; then
|
||
print_warning "Ollama is still starting (models may still be downloading)"
|
||
echo " Check progress with: docker compose --profile ai logs -f ollama"
|
||
else
|
||
print_info "Ollama is running. Models will be pulled in the background."
|
||
echo " Monitor model downloads with: docker compose --profile ai logs -f ollama"
|
||
fi
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Initialize Database
|
||
# =============================================================================
|
||
|
||
print_header "Initializing Database"
|
||
|
||
print_step "Pushing database schema..."
|
||
|
||
if docker compose exec -T api npx drizzle-kit push 2>&1 | tail -5; then
|
||
print_success "Database schema initialized"
|
||
else
|
||
print_error "Failed to initialize database schema"
|
||
echo ""
|
||
echo " Check the logs with: docker compose logs api"
|
||
exit 1
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Restart API to Create Admin User
|
||
# =============================================================================
|
||
|
||
print_step "Restarting API to create admin user..."
|
||
|
||
docker compose restart api
|
||
|
||
sleep 3
|
||
|
||
if ! wait_for_api 30; then
|
||
print_warning "API health check timed out, but it may still be starting"
|
||
fi
|
||
|
||
# Check if admin was created
|
||
print_step "Verifying admin user creation..."
|
||
|
||
sleep 2
|
||
|
||
ADMIN_CHECK=$(docker compose logs api 2>&1 | grep -i "initial admin" | tail -1)
|
||
if echo "$ADMIN_CHECK" | grep -q "created"; then
|
||
print_success "Admin user created successfully"
|
||
elif echo "$ADMIN_CHECK" | grep -q "exists"; then
|
||
print_info "Admin user already exists"
|
||
else
|
||
print_warning "Could not verify admin creation (check logs if login fails)"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Seed Tags
|
||
# =============================================================================
|
||
|
||
print_step "Checking tag seeding..."
|
||
|
||
TAG_CHECK=$(docker compose logs api 2>&1 | grep -i "seed" | tail -1)
|
||
if echo "$TAG_CHECK" | grep -q "Seeded"; then
|
||
print_success "Default tags seeded"
|
||
elif echo "$TAG_CHECK" | grep -q "already"; then
|
||
print_info "Tags already exist"
|
||
fi
|
||
|
||
# =============================================================================
|
||
# Final Status
|
||
# =============================================================================
|
||
|
||
print_header "Setup Complete!"
|
||
|
||
echo -e " ${GREEN}${BOLD}Your Media Manager is ready!${NC}"
|
||
echo ""
|
||
echo " Access the application at:"
|
||
echo ""
|
||
echo -e " ${CYAN}Admin Dashboard:${NC} http://localhost:8080"
|
||
echo -e " ${CYAN}Public Gallery:${NC} http://localhost:3080"
|
||
echo -e " ${CYAN}API:${NC} http://localhost:3001"
|
||
|
||
# Show AI features status
|
||
if [ "$HAS_GPU" = "true" ]; then
|
||
echo ""
|
||
if [ "$START_AI_SERVICES" = "true" ]; then
|
||
echo " AI Services (running):"
|
||
echo -e " ${GREEN}✓${NC} Ollama (Vision + Text models)"
|
||
echo -e " ${GREEN}✓${NC} Whisper (Speech transcription)"
|
||
echo -e " ${GREEN}✓${NC} JoyCaption (Image captioning)"
|
||
echo -e " ${GREEN}✓${NC} Face Recognition"
|
||
echo -e " ${GREEN}✓${NC} YOLO Detection"
|
||
echo -e " ${GREEN}✓${NC} JoyTag (Visual tagging)"
|
||
if [ "$SAFETY_CHECK_ENABLED" = "true" ]; then
|
||
echo -e " ${GREEN}✓${NC} Content Safety Moderation"
|
||
fi
|
||
echo ""
|
||
echo -e " ${CYAN}Ollama:${NC} http://localhost:11435"
|
||
echo -e " ${CYAN}JoyCaption:${NC} http://localhost:11436"
|
||
else
|
||
echo " AI Services (not started):"
|
||
echo -e " ${YELLOW}○${NC} Ollama, Whisper, JoyCaption, Face Recognition, YOLO, JoyTag"
|
||
echo ""
|
||
echo -e " Start with: ${YELLOW}docker compose --profile ai up -d${NC}"
|
||
fi
|
||
fi
|
||
|
||
echo ""
|
||
echo " Login credentials:"
|
||
echo ""
|
||
echo -e " ${CYAN}Email:${NC} $ADMIN_EMAIL"
|
||
echo -e " ${CYAN}Password:${NC} (the password you entered during setup)"
|
||
echo ""
|
||
echo " Useful commands:"
|
||
echo ""
|
||
echo -e " ${YELLOW}docker compose logs -f${NC} # View core service logs"
|
||
echo -e " ${YELLOW}docker compose down${NC} # Stop core services"
|
||
echo -e " ${YELLOW}docker compose up -d${NC} # Start core services"
|
||
echo -e " ${YELLOW}docker compose restart api${NC} # Restart API"
|
||
echo ""
|
||
echo -e " ${YELLOW}docker compose --profile ai up -d${NC} # Start AI services"
|
||
echo -e " ${YELLOW}docker compose --profile ai down${NC} # Stop all (including AI)"
|
||
echo -e " ${YELLOW}docker compose --profile ai logs -f ollama${NC} # View Ollama logs"
|
||
|
||
|
||
echo ""
|
||
echo " Next steps:"
|
||
echo ""
|
||
echo " 1. Log into the admin dashboard"
|
||
echo " 2. Click 'Scan Library' to index your videos"
|
||
echo " 3. Use 'Fractal' section to analyze videos with AI"
|
||
echo " 4. Explore the Library, Jobs, and other sections"
|
||
echo ""
|
||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
echo ""
|