#!/bin/bash # Deployment script for Hex's Garage Sale Catalog # This script automates the deployment process on a Debian server set -e # Exit immediately if a command exits with a non-zero status # Color codes for better readability GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' # No Color # Function to print colored messages print_message() { echo -e "${GREEN}[INFO]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # Check if running as root if [ "$(id -u)" != "0" ]; then print_error "This script must be run as root" exit 1 fi # Get deployment configuration read -p "Enter domain name (e.g., garagesale.example.com): " DOMAIN_NAME read -p "Enter admin password (default: admin123): " ADMIN_PASSWORD ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin123} read -p "Use PostgreSQL instead of SQLite? (y/N): " USE_POSTGRES USE_POSTGRES=${USE_POSTGRES:-n} # Generate a secure secret key SECRET_KEY=$(openssl rand -hex 24) print_message "Beginning deployment process..." # Update system packages print_message "Updating system packages..." apt update && apt upgrade -y # Install required packages print_message "Installing required packages..." apt install -y python3 python3-venv python3-pip nginx wkhtmltopdf # Setup PostgreSQL if requested if [[ "$USE_POSTGRES" =~ ^[Yy]$ ]]; then print_message "Setting up PostgreSQL..." apt install -y postgresql postgresql-contrib systemctl start postgresql systemctl enable postgresql # Generate a secure PostgreSQL password PG_PASSWORD=$(openssl rand -hex 12) # Create PostgreSQL user and database su -c "psql -c \"CREATE DATABASE garagesale;\"" postgres su -c "psql -c \"CREATE USER garagesaleuser WITH PASSWORD '$PG_PASSWORD';\"" postgres su -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE garagesale TO garagesaleuser;\"" postgres DB_URL="postgresql://garagesaleuser:$PG_PASSWORD@localhost/garagesale" print_message "PostgreSQL setup complete." print_warning "PostgreSQL password: $PG_PASSWORD (Please save this somewhere secure)" else DB_URL="sqlite:////var/www/garagesale/garage_sale.db" print_message "Using SQLite for database." fi # Create a dedicated user for the application print_message "Creating application user..." useradd -m -s /bin/bash garagesale || print_warning "User already exists, continuing..." # Set up application directory print_message "Setting up application directory..." mkdir -p /var/www/garagesale cp -r $(dirname "$0")/* /var/www/garagesale/ chown -R garagesale:www-data /var/www/garagesale chmod -R 755 /var/www/garagesale # Create uploads directory with proper permissions mkdir -p /var/www/garagesale/app/static/uploads chown -R garagesale:www-data /var/www/garagesale/app/static/uploads chmod -R 775 /var/www/garagesale/app/static/uploads # Set up virtual environment and install dependencies print_message "Setting up Python virtual environment and dependencies..." cd /var/www/garagesale su -c "python3 -m venv venv" garagesale su -c "source venv/bin/activate && pip install -r requirements.txt && pip install gunicorn" garagesale if [[ "$USE_POSTGRES" =~ ^[Yy]$ ]]; then su -c "source venv/bin/activate && pip install psycopg2-binary" garagesale fi # Create environment file print_message "Creating environment file..." cat > /var/www/garagesale/.env << EOF SECRET_KEY="$SECRET_KEY" ADMIN_PASSWORD="$ADMIN_PASSWORD" DATABASE_URL="$DB_URL" EOF chown garagesale:garagesale /var/www/garagesale/.env chmod 600 /var/www/garagesale/.env # Create wsgi.py file print_message "Creating WSGI file..." cat > /var/www/garagesale/wsgi.py << 'EOF' from app import create_app app = create_app() if __name__ == "__main__": app.run() EOF chown garagesale:garagesale /var/www/garagesale/wsgi.py # Initialize the database print_message "Initializing the database..." cd /var/www/garagesale su -c "source venv/bin/activate && python init_db.py" garagesale # Set up Gunicorn service print_message "Setting up Gunicorn service..." cat > /etc/systemd/system/garagesale.service << EOF [Unit] Description=Gunicorn instance to serve Hex's Garage Sale Catalog After=network.target [Service] User=garagesale Group=www-data WorkingDirectory=/var/www/garagesale Environment="PATH=/var/www/garagesale/venv/bin" EnvironmentFile=/var/www/garagesale/.env ExecStart=/var/www/garagesale/venv/bin/gunicorn --workers 3 --bind unix:garagesale.sock -m 007 wsgi:app [Install] WantedBy=multi-user.target EOF # Enable and start Gunicorn service print_message "Starting Gunicorn service..." systemctl daemon-reload systemctl start garagesale systemctl enable garagesale # Set up Nginx print_message "Setting up Nginx..." cat > /etc/nginx/sites-available/garagesale << EOF server { listen 80; server_name $DOMAIN_NAME; location /static { alias /var/www/garagesale/app/static; } location / { proxy_pass http://unix:/var/www/garagesale/garagesale.sock; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; } } EOF # Enable the Nginx site ln -sf /etc/nginx/sites-available/garagesale /etc/nginx/sites-enabled/ nginx -t && systemctl restart nginx print_message "Basic deployment complete!" # Set up SSL with Let's Encrypt read -p "Do you want to set up SSL with Let's Encrypt? (y/N): " SETUP_SSL SETUP_SSL=${SETUP_SSL:-n} if [[ "$SETUP_SSL" =~ ^[Yy]$ ]]; then print_message "Setting up SSL with Let's Encrypt..." apt install -y certbot python3-certbot-nginx certbot --nginx -d "$DOMAIN_NAME" print_message "SSL setup complete!" fi print_message "Deployment completed successfully!" print_message "You can now access your application at: http://$DOMAIN_NAME" if [[ "$SETUP_SSL" =~ ^[Yy]$ ]]; then print_message "Or securely at: https://$DOMAIN_NAME" fi print_message "Admin interface is available at: http://$DOMAIN_NAME/admin" print_message "Admin password: $ADMIN_PASSWORD" exit 0