#!/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}" } # Install frontend dependencies install_frontend_dependencies() { echo -e "${BLUE}📦 Installing frontend dependencies...${NC}" if [ ! -d "frontend" ]; then echo -e "${RED}❌ frontend directory not found${NC}" return 1 fi cd frontend if [ ! -f "package.json" ]; then echo -e "${RED}❌ package.json not found${NC}" cd .. return 1 fi echo -e "${BLUE} Running npm install...${NC}" npm install echo -e "${GREEN} ✅ Frontend dependencies installed${NC}" cd .. } # 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 frontend .env file if it doesn't exist if [ ! -f "frontend/.env" ]; then echo -e "${BLUE} Creating frontend/.env file...${NC}" cat > frontend/.env << 'EOF' # Backend API URL (must be accessible from browsers) VITE_API_URL=http://127.0.0.1:8000 EOF echo -e "${GREEN} ✅ frontend/.env file created${NC}" else echo -e "${GREEN} ✅ frontend/.env 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 "" # 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 src.web.app:app --host 127.0.0.1 --port 8000${NC}" echo "" echo -e "4. ${YELLOW}In another terminal, start the frontend:${NC}" echo -e " ${BLUE} cd frontend${NC}" echo -e " ${BLUE} npm run dev${NC}" echo "" echo -e "5. ${YELLOW}Access the application:${NC}" echo -e " ${BLUE} http://localhost:3000${NC}" echo "" echo -e "${GREEN}For more information, see README.md${NC}" echo "" } # Run main function main