#!/bin/bash # MYP Backend Installation Script for Debian # This script installs and configures the MYP backend on a Debian-based system set -e # Exit immediately if a command exits with non-zero status SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" LOG_FILE="$SCRIPT_DIR/backend-install.log" # Function for logging with timestamps log() { local timestamp=$(date +"%Y-%m-%d %H:%M:%S") echo -e "[$timestamp] $1" | tee -a "$LOG_FILE" } # Function to check if a command exists command_exists() { command -v "$1" >/dev/null 2>&1 } # Clear log file > "$LOG_FILE" log "===== Starting MYP Backend Installation =====" log "Installation directory: $SCRIPT_DIR" # Check for root privileges if [ "$EUID" -ne 0 ]; then log "ERROR: This script must be run as root" exit 1 fi # System update log "Updating system packages..." apt update -y >> "$LOG_FILE" 2>&1 apt upgrade -y >> "$LOG_FILE" 2>&1 # Install required packages log "Installing required packages..." apt install -y python3 python3-venv python3-pip sqlite3 >> "$LOG_FILE" 2>&1 # Create Python virtual environment log "Creating Python virtual environment..." cd "$SCRIPT_DIR" if [ -d "venv" ]; then log "Found existing virtual environment, removing..." rm -rf venv fi python3 -m venv venv >> "$LOG_FILE" 2>&1 source venv/bin/activate log "Upgrading pip..." pip install --upgrade pip >> "$LOG_FILE" 2>&1 # Install Python dependencies log "Installing Python dependencies..." if [ -f "requirements.txt" ]; then pip install -r requirements.txt >> "$LOG_FILE" 2>&1 else log "ERROR: requirements.txt not found" exit 1 fi # Setup Bootstrap for offline usage log "Setting up Bootstrap for offline usage..." mkdir -p "$SCRIPT_DIR/static/css" "$SCRIPT_DIR/static/js" # Download non-minified Bootstrap CSS and JS files log "Downloading Bootstrap files for offline usage..." wget -q -O "$SCRIPT_DIR/static/css/bootstrap.css" "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.css" || { log "WARNING: Could not download Bootstrap CSS. Creating placeholder..." echo "/* Bootstrap 5.3.2 offline placeholder */" > "$SCRIPT_DIR/static/css/bootstrap.css" echo "/* Please manually download the full unminified version from: */" >> "$SCRIPT_DIR/static/css/bootstrap.css" echo "/* https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.css */" >> "$SCRIPT_DIR/static/css/bootstrap.css" } wget -q -O "$SCRIPT_DIR/static/js/bootstrap.bundle.js" "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.js" || { log "WARNING: Could not download Bootstrap JS. Creating placeholder..." echo "/* Bootstrap 5.3.2 bundle offline placeholder */" > "$SCRIPT_DIR/static/js/bootstrap.bundle.js" echo "/* Please manually download the full unminified version from: */" >> "$SCRIPT_DIR/static/js/bootstrap.bundle.js" echo "/* https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.js */" >> "$SCRIPT_DIR/static/js/bootstrap.bundle.js" } # Create database directory if it doesn't exist log "Setting up database directories..." mkdir -p instance/backups # Check if .env file exists if [ ! -f "$SCRIPT_DIR/.env" ]; then log "Creating .env file template (IMPORTANT: Edit with your configuration)..." cat > "$SCRIPT_DIR/.env" << EOF # MYP Backend Environment Configuration # IMPORTANT: Replace these values with your actual configuration! SECRET_KEY=generate_a_secure_random_key DATABASE_PATH=instance/myp_backend.db # Tapo P115 Smart Plug credentials TAPO_USERNAME=your_tapo_email TAPO_PASSWORD=your_tapo_password # Printer to Smart Plug mapping (JSON format) # Format: {"Printer Name": "192.168.x.x", "Another Printer": "192.168.x.y"} PRINTERS={"Example Printer": "192.168.1.100"} EOF log "ATTENTION: .env file has been created with placeholder values" log " Please edit .env with your actual configuration before continuing" read -p "Press Enter to continue after editing .env..." fi # Initialize the database log "Initializing database..." if [ -f "$SCRIPT_DIR/development/initialize_myp_database.sh" ]; then bash "$SCRIPT_DIR/development/initialize_myp_database.sh" >> "$LOG_FILE" 2>&1 log "Database initialized successfully" else log "WARNING: initialize_myp_database.sh not found, manual setup may be required" # Create empty database touch instance/myp_backend.db log "Created empty database file" fi # Setup cron job log "Setting up cron job for maintenance tasks..." CURRENT_USER=$(who am i | awk '{print $1}') CRON_JOB="*/5 * * * * cd $SCRIPT_DIR && source venv/bin/activate && flask check-jobs" # Create a temporary file with the current crontab plus our new job TEMP_CRON=$(mktemp) crontab -l 2>/dev/null | grep -v "$SCRIPT_DIR.*check-jobs" > "$TEMP_CRON" || true echo "$CRON_JOB" >> "$TEMP_CRON" crontab "$TEMP_CRON" rm "$TEMP_CRON" log "Cron job installed. Maintenance tasks will run every 5 minutes" # Test the application log "Testing backend application..." source venv/bin/activate cd "$SCRIPT_DIR" if python -c "import app" 2>> "$LOG_FILE"; then log "Import test successful" else log "WARNING: Import test failed, check the log file for details" fi # Generate systemd service file log "Creating systemd service..." cat > /etc/systemd/system/myp-backend.service << EOF [Unit] Description=MYP Backend Service After=network.target [Service] User=$CURRENT_USER WorkingDirectory=$SCRIPT_DIR ExecStart=$SCRIPT_DIR/venv/bin/gunicorn --bind 0.0.0.0:5000 app:app Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF # Reload systemd and enable the service systemctl daemon-reload systemctl enable myp-backend.service log "Installation complete!" log "" log "To start the backend service, run: systemctl start myp-backend" log "To check service status, run: systemctl status myp-backend" log "To view logs, run: journalctl -u myp-backend -f" log "" log "Configuration file is at: $SCRIPT_DIR/.env" log "Make sure to configure your Tapo smart plug credentials and printer mapping in this file" log "" log "For development mode, run: cd $SCRIPT_DIR && source venv/bin/activate && python app.py" log "" log "To run tests, use: cd $SCRIPT_DIR && source venv/bin/activate && python -m unittest development/tests/tests.py" log "" log "For issues, check the log file at: $LOG_FILE"