This commit introduces a new function in the `install.sh` script to download DeepFace model weights, enhancing the setup process for users. The function checks for the presence of DeepFace and attempts to download the ArcFace model weights, providing fallback options and user-friendly messages for manual download if automatic attempts fail. This improvement streamlines the initial configuration for facial recognition capabilities in the application.
492 lines
16 KiB
Bash
Executable File
492 lines
16 KiB
Bash
Executable File
#!/bin/bash
|
|
# Comprehensive installation script for PunimTag Web
|
|
# Installs all system dependencies, Python packages, and frontend dependencies
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Project root directory
|
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$PROJECT_ROOT"
|
|
|
|
echo -e "${BLUE}╔══════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${BLUE}║ PunimTag Web - Comprehensive Installation Script ║${NC}"
|
|
echo -e "${BLUE}╚══════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
# Function to check if command exists
|
|
command_exists() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
# Function to check Python version
|
|
check_python_version() {
|
|
if command_exists python3; then
|
|
PYTHON_VERSION=$(python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))')
|
|
PYTHON_MAJOR=$(echo "$PYTHON_VERSION" | cut -d. -f1)
|
|
PYTHON_MINOR=$(echo "$PYTHON_VERSION" | cut -d. -f2)
|
|
|
|
if [ "$PYTHON_MAJOR" -lt 3 ] || ([ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 12 ]); then
|
|
echo -e "${RED}❌ Python 3.12 or higher is required. Found: Python $PYTHON_VERSION${NC}"
|
|
return 1
|
|
else
|
|
echo -e "${GREEN}✅ Python $PYTHON_VERSION found${NC}"
|
|
return 0
|
|
fi
|
|
else
|
|
echo -e "${RED}❌ Python 3 is not installed${NC}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Function to check Node.js version
|
|
check_node_version() {
|
|
if command_exists node; then
|
|
NODE_VERSION=$(node -v | sed 's/v//')
|
|
NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d. -f1)
|
|
|
|
if [ "$NODE_MAJOR" -lt 18 ]; then
|
|
echo -e "${RED}❌ Node.js 18 or higher is required. Found: Node.js $NODE_VERSION${NC}"
|
|
return 1
|
|
else
|
|
echo -e "${GREEN}✅ Node.js $NODE_VERSION found${NC}"
|
|
return 0
|
|
fi
|
|
else
|
|
echo -e "${RED}❌ Node.js is not installed${NC}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Detect OS
|
|
detect_os() {
|
|
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
if [ -f /etc/os-release ]; then
|
|
. /etc/os-release
|
|
OS=$ID
|
|
else
|
|
OS="linux"
|
|
fi
|
|
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|
OS="macos"
|
|
else
|
|
OS="unknown"
|
|
fi
|
|
echo "$OS"
|
|
}
|
|
|
|
# Install system dependencies (Linux only)
|
|
install_system_dependencies() {
|
|
local os=$(detect_os)
|
|
|
|
if [[ "$os" != "ubuntu" && "$os" != "debian" ]]; then
|
|
echo -e "${YELLOW}⚠️ Automatic system dependency installation is only supported on Ubuntu/Debian${NC}"
|
|
echo -e "${YELLOW} Please install PostgreSQL and Redis manually for other systems${NC}"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${BLUE}📦 Installing system dependencies...${NC}"
|
|
|
|
# Update package list
|
|
sudo apt update
|
|
|
|
# Install PostgreSQL
|
|
if ! command_exists psql; then
|
|
echo -e "${BLUE} Installing PostgreSQL...${NC}"
|
|
sudo apt install -y postgresql postgresql-contrib
|
|
sudo systemctl start postgresql
|
|
sudo systemctl enable postgresql
|
|
echo -e "${GREEN} ✅ PostgreSQL installed${NC}"
|
|
else
|
|
echo -e "${GREEN} ✅ PostgreSQL already installed${NC}"
|
|
fi
|
|
|
|
# Install Redis
|
|
if ! command_exists redis-cli; then
|
|
echo -e "${BLUE} Installing Redis...${NC}"
|
|
sudo apt install -y redis-server
|
|
sudo systemctl start redis-server
|
|
sudo systemctl enable redis-server
|
|
echo -e "${GREEN} ✅ Redis installed${NC}"
|
|
else
|
|
echo -e "${GREEN} ✅ Redis already installed${NC}"
|
|
fi
|
|
|
|
# Verify Redis is running
|
|
if redis-cli ping >/dev/null 2>&1; then
|
|
echo -e "${GREEN} ✅ Redis is running${NC}"
|
|
else
|
|
echo -e "${YELLOW} ⚠️ Redis is not running. Starting Redis...${NC}"
|
|
sudo systemctl start redis-server || redis-server --daemonize yes
|
|
fi
|
|
}
|
|
|
|
# Setup PostgreSQL databases
|
|
setup_databases() {
|
|
echo -e "${BLUE}🗄️ Setting up PostgreSQL databases...${NC}"
|
|
|
|
if ! command_exists psql; then
|
|
echo -e "${YELLOW}⚠️ PostgreSQL is not installed. Skipping database setup.${NC}"
|
|
echo -e "${YELLOW} Please install PostgreSQL and run: ./scripts/setup_postgresql.sh${NC}"
|
|
return 0
|
|
fi
|
|
|
|
# Start PostgreSQL if not running
|
|
if ! sudo systemctl is-active --quiet postgresql; then
|
|
echo -e "${BLUE} Starting PostgreSQL service...${NC}"
|
|
sudo systemctl start postgresql
|
|
fi
|
|
|
|
# Create user and databases
|
|
echo -e "${BLUE} Creating database user and databases...${NC}"
|
|
sudo -u postgres psql << 'EOF' || true
|
|
-- Create user if it doesn't exist
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT FROM pg_user WHERE usename = 'punimtag') THEN
|
|
CREATE USER punimtag WITH PASSWORD 'punimtag_password';
|
|
END IF;
|
|
END
|
|
$$;
|
|
|
|
-- Create main database if it doesn't exist
|
|
SELECT 'CREATE DATABASE punimtag OWNER punimtag'
|
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'punimtag')\gexec
|
|
|
|
-- Create auth database if it doesn't exist
|
|
SELECT 'CREATE DATABASE punimtag_auth OWNER punimtag'
|
|
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'punimtag_auth')\gexec
|
|
|
|
-- Grant privileges
|
|
GRANT ALL PRIVILEGES ON DATABASE punimtag TO punimtag;
|
|
GRANT ALL PRIVILEGES ON DATABASE punimtag_auth TO punimtag;
|
|
\q
|
|
EOF
|
|
|
|
echo -e "${GREEN} ✅ Databases created${NC}"
|
|
}
|
|
|
|
# Create Python virtual environment
|
|
setup_python_venv() {
|
|
echo -e "${BLUE}🐍 Setting up Python virtual environment...${NC}"
|
|
|
|
if [ ! -d "venv" ]; then
|
|
echo -e "${BLUE} Creating virtual environment...${NC}"
|
|
python3 -m venv venv
|
|
echo -e "${GREEN} ✅ Virtual environment created${NC}"
|
|
else
|
|
echo -e "${GREEN} ✅ Virtual environment already exists${NC}"
|
|
fi
|
|
|
|
# Activate virtual environment
|
|
source venv/bin/activate
|
|
|
|
# Upgrade pip
|
|
echo -e "${BLUE} Upgrading pip...${NC}"
|
|
pip install --upgrade pip --quiet
|
|
|
|
echo -e "${GREEN} ✅ Python environment ready${NC}"
|
|
}
|
|
|
|
# Install Python dependencies
|
|
install_python_dependencies() {
|
|
echo -e "${BLUE}📦 Installing Python dependencies...${NC}"
|
|
|
|
if [ ! -f "requirements.txt" ]; then
|
|
echo -e "${RED}❌ requirements.txt not found${NC}"
|
|
return 1
|
|
fi
|
|
|
|
source venv/bin/activate
|
|
pip install -r requirements.txt
|
|
|
|
echo -e "${GREEN} ✅ Python dependencies installed${NC}"
|
|
}
|
|
|
|
# Download DeepFace model weights (optional, but recommended)
|
|
download_deepface_models() {
|
|
echo -e "${BLUE}🤖 Downloading DeepFace model weights (optional)...${NC}"
|
|
|
|
source venv/bin/activate
|
|
|
|
# Check if deepface is installed
|
|
if ! python3 -c "import deepface" 2>/dev/null; then
|
|
echo -e "${YELLOW} ⚠️ DeepFace not installed, skipping model download${NC}"
|
|
return 0
|
|
fi
|
|
|
|
# Create weights directory
|
|
mkdir -p ~/.deepface/weights
|
|
|
|
# Check if ArcFace weights already exist
|
|
if [ -f ~/.deepface/weights/arcface_weights.h5 ]; then
|
|
echo -e "${GREEN} ✅ ArcFace model weights already exist${NC}"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "${BLUE} Downloading ArcFace model weights (~131MB, this may take a few minutes)...${NC}"
|
|
|
|
# Try to download using wget (more reliable than Python download in worker)
|
|
if command_exists wget; then
|
|
if wget -q --show-progress \
|
|
https://github.com/serengil/deepface_models/releases/download/v1.0/arcface_weights.h5 \
|
|
-O ~/.deepface/weights/arcface_weights.h5; then
|
|
echo -e "${GREEN} ✅ ArcFace model weights downloaded successfully${NC}"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Fallback: try with Python (may fail in some environments)
|
|
echo -e "${YELLOW} ⚠️ wget failed, trying Python download...${NC}"
|
|
if python3 << 'PYTHON'
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from deepface import DeepFace
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
# Create a dummy image to trigger model download
|
|
dummy_img = Image.new('RGB', (100, 100), color='black')
|
|
dummy_array = np.array(dummy_img)
|
|
|
|
# This will trigger model download
|
|
try:
|
|
DeepFace.represent(
|
|
img_path=dummy_array,
|
|
model_name="ArcFace",
|
|
detector_backend="retinaface",
|
|
enforce_detection=False,
|
|
align=True,
|
|
)
|
|
print("✅ Model weights downloaded successfully")
|
|
sys.exit(0)
|
|
except Exception as e:
|
|
if "arcface_weights" in str(e).lower():
|
|
print(f"⚠️ Download failed: {e}")
|
|
print(" You can download manually later or the worker will try again")
|
|
sys.exit(1)
|
|
# Other errors are OK (like no faces found)
|
|
print("✅ Model weights are available")
|
|
sys.exit(0)
|
|
except ImportError:
|
|
print("⚠️ DeepFace not available")
|
|
sys.exit(0)
|
|
except Exception as e:
|
|
print(f"⚠️ Error: {e}")
|
|
sys.exit(1)
|
|
PYTHON
|
|
then
|
|
echo -e "${GREEN} ✅ DeepFace models ready${NC}"
|
|
else
|
|
echo -e "${YELLOW} ⚠️ Automatic download failed. Models will be downloaded on first use.${NC}"
|
|
echo -e "${YELLOW} ⚠️ To download manually, run:${NC}"
|
|
echo -e "${BLUE} mkdir -p ~/.deepface/weights${NC}"
|
|
echo -e "${BLUE} wget https://github.com/serengil/deepface_models/releases/download/v1.0/arcface_weights.h5 -O ~/.deepface/weights/arcface_weights.h5${NC}"
|
|
fi
|
|
}
|
|
|
|
# Install frontend dependencies
|
|
install_frontend_dependencies() {
|
|
echo -e "${BLUE}📦 Installing frontend dependencies...${NC}"
|
|
|
|
# Install admin frontend
|
|
if [ -d "admin-frontend" ]; then
|
|
echo -e "${BLUE} Installing admin frontend dependencies...${NC}"
|
|
cd admin-frontend
|
|
if [ -f "package.json" ]; then
|
|
npm install
|
|
echo -e "${GREEN} ✅ Admin frontend dependencies installed${NC}"
|
|
fi
|
|
cd ..
|
|
fi
|
|
|
|
# Install viewer frontend
|
|
if [ -d "viewer-frontend" ]; then
|
|
echo -e "${BLUE} Installing viewer frontend dependencies...${NC}"
|
|
cd viewer-frontend
|
|
if [ -f "package.json" ]; then
|
|
npm install
|
|
echo -e "${GREEN} ✅ Viewer frontend dependencies installed${NC}"
|
|
fi
|
|
cd ..
|
|
fi
|
|
}
|
|
|
|
# Create .env file if it doesn't exist
|
|
create_env_file() {
|
|
echo -e "${BLUE}⚙️ Setting up environment configuration...${NC}"
|
|
|
|
if [ ! -f ".env" ]; then
|
|
echo -e "${BLUE} Creating .env file...${NC}"
|
|
cat > .env << 'EOF'
|
|
# Database (PostgreSQL by default)
|
|
DATABASE_URL=postgresql+psycopg2://punimtag:punimtag_password@localhost:5432/punimtag
|
|
|
|
# Auth Database (for frontend website user accounts - separate from main database)
|
|
DATABASE_URL_AUTH=postgresql+psycopg2://punimtag:punimtag_password@localhost:5432/punimtag_auth
|
|
|
|
# JWT Secrets (change in production!)
|
|
SECRET_KEY=dev-secret-key-change-in-production
|
|
|
|
# Single-user credentials (change in production!)
|
|
ADMIN_USERNAME=admin
|
|
ADMIN_PASSWORD=admin
|
|
|
|
# Photo storage directory (default: data/uploads)
|
|
PHOTO_STORAGE_DIR=data/uploads
|
|
EOF
|
|
echo -e "${GREEN} ✅ .env file created${NC}"
|
|
echo -e "${YELLOW} ⚠️ Please review and update .env file with your configuration${NC}"
|
|
else
|
|
echo -e "${GREEN} ✅ .env file already exists${NC}"
|
|
fi
|
|
|
|
# Create admin frontend .env file if it doesn't exist
|
|
if [ -d "admin-frontend" ] && [ ! -f "admin-frontend/.env" ]; then
|
|
echo -e "${BLUE} Creating admin-frontend/.env file...${NC}"
|
|
cat > admin-frontend/.env << 'EOF'
|
|
# Backend API URL (must be accessible from browsers)
|
|
VITE_API_URL=http://127.0.0.1:8000
|
|
EOF
|
|
echo -e "${GREEN} ✅ admin-frontend/.env file created${NC}"
|
|
elif [ -d "admin-frontend" ]; then
|
|
echo -e "${GREEN} ✅ admin-frontend/.env file already exists${NC}"
|
|
fi
|
|
|
|
# Create viewer frontend .env file if it doesn't exist
|
|
if [ -d "viewer-frontend" ] && [ ! -f "viewer-frontend/.env.local" ]; then
|
|
echo -e "${BLUE} Creating viewer-frontend/.env.local file...${NC}"
|
|
cat > viewer-frontend/.env.local << 'EOF'
|
|
# Database connection (read-only recommended)
|
|
DATABASE_URL=postgresql://punimtag:punimtag_password@localhost:5432/punimtag
|
|
|
|
# Auth database connection
|
|
DATABASE_URL_AUTH=postgresql://punimtag:punimtag_password@localhost:5432/punimtag_auth
|
|
|
|
# NextAuth configuration
|
|
NEXTAUTH_URL=http://localhost:3001
|
|
NEXTAUTH_SECRET=dev-secret-key-change-in-production
|
|
EOF
|
|
echo -e "${GREEN} ✅ viewer-frontend/.env.local file created${NC}"
|
|
elif [ -d "viewer-frontend" ]; then
|
|
echo -e "${GREEN} ✅ viewer-frontend/.env.local file already exists${NC}"
|
|
fi
|
|
}
|
|
|
|
# Create data directories
|
|
create_data_directories() {
|
|
echo -e "${BLUE}📁 Creating data directories...${NC}"
|
|
|
|
mkdir -p data/uploads
|
|
mkdir -p data/thumbnails
|
|
|
|
echo -e "${GREEN} ✅ Data directories created${NC}"
|
|
}
|
|
|
|
# Main installation function
|
|
main() {
|
|
echo -e "${BLUE}🔍 Checking prerequisites...${NC}"
|
|
echo ""
|
|
|
|
# Check Python
|
|
if ! check_python_version; then
|
|
echo -e "${RED}❌ Please install Python 3.12 or higher${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check Node.js
|
|
if ! check_node_version; then
|
|
echo -e "${RED}❌ Please install Node.js 18 or higher${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check npm
|
|
if ! command_exists npm; then
|
|
echo -e "${RED}❌ npm is not installed${NC}"
|
|
exit 1
|
|
else
|
|
echo -e "${GREEN}✅ npm found${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BLUE}🚀 Starting installation...${NC}"
|
|
echo ""
|
|
|
|
# Install system dependencies (Linux only)
|
|
install_system_dependencies
|
|
echo ""
|
|
|
|
# Setup databases
|
|
setup_databases
|
|
echo ""
|
|
|
|
# Setup Python environment
|
|
setup_python_venv
|
|
echo ""
|
|
|
|
# Install Python dependencies
|
|
install_python_dependencies
|
|
echo ""
|
|
|
|
# Download DeepFace model weights (optional)
|
|
download_deepface_models
|
|
echo ""
|
|
|
|
# Install frontend dependencies
|
|
install_frontend_dependencies
|
|
echo ""
|
|
|
|
# Create .env files
|
|
create_env_file
|
|
echo ""
|
|
|
|
# Create data directories
|
|
create_data_directories
|
|
echo ""
|
|
|
|
# Success message
|
|
echo -e "${GREEN}╔══════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${GREEN}║ ✅ Installation Complete! ║${NC}"
|
|
echo -e "${GREEN}╚══════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}📋 Next Steps:${NC}"
|
|
echo ""
|
|
echo -e "1. ${YELLOW}Review and update .env file${NC} (if needed):"
|
|
echo -e " ${BLUE} nano .env${NC}"
|
|
echo ""
|
|
echo -e "2. ${YELLOW}Activate the virtual environment:${NC}"
|
|
echo -e " ${BLUE} source venv/bin/activate${NC}"
|
|
echo ""
|
|
echo -e "3. ${YELLOW}Start the backend API:${NC}"
|
|
echo -e " ${BLUE} export PYTHONPATH=$PROJECT_ROOT${NC}"
|
|
echo -e " ${BLUE} uvicorn backend.app:app --host 127.0.0.1 --port 8000${NC}"
|
|
echo ""
|
|
echo -e "4. ${YELLOW}In another terminal, start the admin frontend:${NC}"
|
|
echo -e " ${BLUE} cd admin-frontend${NC}"
|
|
echo -e " ${BLUE} npm run dev${NC}"
|
|
echo ""
|
|
echo -e "5. ${YELLOW}In another terminal, start the viewer frontend (optional):${NC}"
|
|
echo -e " ${BLUE} cd viewer-frontend${NC}"
|
|
echo -e " ${BLUE} npm run dev${NC}"
|
|
echo ""
|
|
echo -e "6. ${YELLOW}Access the applications:${NC}"
|
|
echo -e " ${BLUE} Admin: http://localhost:3000${NC}"
|
|
echo -e " ${BLUE} Viewer: http://localhost:3001${NC}"
|
|
echo ""
|
|
echo -e "${GREEN}For more information, see README.md${NC}"
|
|
echo ""
|
|
}
|
|
|
|
# Run main function
|
|
main
|
|
|