File: /var/www/indoadvisory_new/web/webapp/deploy.sh
#!/bin/bash
# Indo Advisory Deployment Script for VPS
# Enterprise-grade deployment with security and monitoring
# Usage: chmod +x deploy.sh && ./deploy.sh [production|staging]
set -e  # Exit on any error
# Configuration
APP_NAME="indo-advisory"
APP_USER="www-data"
APP_DIR="/var/www/$APP_NAME"
REPO_URL="https://github.com/your-username/indo-advisory.git"  # Update this
BRANCH="main"
NODE_VERSION="18"
PM2_INSTANCES="max"
BACKUP_DIR="/var/backups/$APP_NAME"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging function
log() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
error() {
    echo -e "${RED}[ERROR]${NC} $1" >&2
}
warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}
info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}
# Check if running as root
check_root() {
    if [[ $EUID -eq 0 ]]; then
        error "This script should not be run as root for security reasons"
        error "Please run as a regular user with sudo privileges"
        exit 1
    fi
}
# Install system dependencies
install_dependencies() {
    log "Installing system dependencies..."
    
    # Update package list
    sudo apt update
    
    # Install required packages
    sudo apt install -y \
        curl \
        wget \
        git \
        build-essential \
        nginx \
        postgresql \
        postgresql-contrib \
        ufw \
        fail2ban \
        certbot \
        python3-certbot-nginx \
        htop \
        unzip
    
    # Install Node.js via NodeSource
    if ! command -v node &> /dev/null; then
        log "Installing Node.js $NODE_VERSION..."
        curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | sudo -E bash -
        sudo apt-get install -y nodejs
    fi
    
    # Install PM2 globally
    if ! command -v pm2 &> /dev/null; then
        log "Installing PM2..."
        sudo npm install -g pm2
        pm2 install pm2-logrotate
    fi
    
    log "System dependencies installed successfully"
}
# Setup PostgreSQL database
setup_database() {
    log "Setting up PostgreSQL database..."
    
    # Create database user and database
    sudo -u postgres psql -c "CREATE DATABASE ${APP_NAME}_production;" 2>/dev/null || true
    sudo -u postgres psql -c "CREATE USER ${APP_NAME}_user WITH PASSWORD 'secure_production_password';" 2>/dev/null || true
    sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE ${APP_NAME}_production TO ${APP_NAME}_user;" 2>/dev/null || true
    sudo -u postgres psql -c "ALTER USER ${APP_NAME}_user CREATEDB;" 2>/dev/null || true
    
    log "Database setup completed"
}
# Setup application directory and permissions
setup_app_directory() {
    log "Setting up application directory..."
    
    # Create application directory
    sudo mkdir -p $APP_DIR
    sudo mkdir -p $APP_DIR/{logs,uploads,backups}
    
    # Set proper ownership
    sudo chown -R $USER:$APP_USER $APP_DIR
    sudo chmod -R 755 $APP_DIR
    sudo chmod -R 775 $APP_DIR/{logs,uploads,backups}
    
    log "Application directory setup completed"
}
# Clone or update repository
deploy_code() {
    log "Deploying application code..."
    
    if [ -d "$APP_DIR/.git" ]; then
        log "Updating existing repository..."
        cd $APP_DIR
        git fetch origin
        git reset --hard origin/$BRANCH
    else
        log "Cloning repository..."
        sudo rm -rf $APP_DIR/*
        git clone -b $BRANCH $REPO_URL $APP_DIR
        cd $APP_DIR
    fi
    
    # Set proper permissions
    sudo chown -R $USER:$APP_USER $APP_DIR
    
    log "Code deployment completed"
}
# Install Node.js dependencies
install_node_dependencies() {
    log "Installing Node.js dependencies..."
    
    cd $APP_DIR
    
    # Install production dependencies
    npm ci --only=production
    
    log "Node.js dependencies installed"
}
# Setup environment configuration
setup_environment() {
    log "Setting up environment configuration..."
    
    cd $APP_DIR
    
    # Create production environment file
    if [ ! -f ".env" ]; then
        cp .env.example .env
        
        # Update environment variables for production
        sed -i "s/NODE_ENV=development/NODE_ENV=production/" .env
        sed -i "s/DB_HOST=localhost/DB_HOST=localhost/" .env
        sed -i "s/DB_NAME=indo_advisory/DB_NAME=${APP_NAME}_production/" .env
        sed -i "s/DB_USER=indo_user/DB_USER=${APP_NAME}_user/" .env
        
        warning "Please update the .env file with your production values:"
        warning "- Database password"
        warning "- Session secrets"
        warning "- SMTP settings"
        warning "- Domain name"
    fi
    
    log "Environment configuration completed"
}
# Run database migrations
run_migrations() {
    log "Running database migrations..."
    
    cd $APP_DIR
    
    # Run migrations
    npm run migrate
    
    # Seed initial data (only if needed)
    read -p "Do you want to seed initial data? (y/N): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        npm run seed
    fi
    
    log "Database migrations completed"
}
# Setup Nginx configuration
setup_nginx() {
    log "Setting up Nginx configuration..."
    
    # Copy Nginx configuration
    sudo cp $APP_DIR/nginx.conf /etc/nginx/sites-available/$APP_NAME
    
    # Enable site
    sudo ln -sf /etc/nginx/sites-available/$APP_NAME /etc/nginx/sites-enabled/
    
    # Remove default site
    sudo rm -f /etc/nginx/sites-enabled/default
    
    # Test Nginx configuration
    sudo nginx -t
    
    # Restart Nginx
    sudo systemctl restart nginx
    sudo systemctl enable nginx
    
    log "Nginx setup completed"
}
# Setup SSL certificate
setup_ssl() {
    log "Setting up SSL certificate..."
    
    read -p "Enter your domain name (e.g., indoadvisory.com): " domain
    
    if [ ! -z "$domain" ]; then
        # Obtain SSL certificate
        sudo certbot --nginx -d $domain -d www.$domain
        
        # Auto-renewal
        sudo systemctl enable certbot.timer
        
        log "SSL certificate setup completed"
    else
        warning "Skipping SSL setup - no domain provided"
    fi
}
# Setup firewall
setup_firewall() {
    log "Setting up firewall..."
    
    # Reset UFW to defaults
    sudo ufw --force reset
    
    # Set default policies
    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    
    # Allow essential services
    sudo ufw allow ssh
    sudo ufw allow http
    sudo ufw allow https
    
    # Allow specific ports if needed
    # sudo ufw allow 3000  # Node.js (only if direct access needed)
    
    # Enable firewall
    sudo ufw --force enable
    
    log "Firewall setup completed"
}
# Setup Fail2Ban
setup_fail2ban() {
    log "Setting up Fail2Ban..."
    
    # Create custom jail configuration
    sudo tee /etc/fail2ban/jail.local > /dev/null <<EOF
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[nginx-http-auth]
enabled = true
[nginx-limit-req]
enabled = true
logpath = /var/log/nginx/*error.log
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 3
EOF
    
    # Restart Fail2Ban
    sudo systemctl restart fail2ban
    sudo systemctl enable fail2ban
    
    log "Fail2Ban setup completed"
}
# Start application with PM2
start_application() {
    log "Starting application with PM2..."
    
    cd $APP_DIR
    
    # Stop existing processes
    pm2 delete $APP_NAME 2>/dev/null || true
    
    # Start application
    pm2 start ecosystem.config.js --env production
    
    # Save PM2 configuration
    pm2 save
    
    # Setup PM2 startup script
    sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u $USER --hp /home/$USER
    
    log "Application started successfully"
}
# Create backup script
setup_backup() {
    log "Setting up backup system..."
    
    # Create backup directory
    sudo mkdir -p $BACKUP_DIR
    sudo chown $USER:$APP_USER $BACKUP_DIR
    
    # Create backup script
    sudo tee /usr/local/bin/indo-advisory-backup.sh > /dev/null <<EOF
#!/bin/bash
BACKUP_DIR="$BACKUP_DIR"
TIMESTAMP=\$(date +%Y%m%d_%H%M%S)
# Database backup
pg_dump -h localhost -U ${APP_NAME}_user -d ${APP_NAME}_production > \$BACKUP_DIR/database_\$TIMESTAMP.sql
# Application backup
tar -czf \$BACKUP_DIR/app_\$TIMESTAMP.tar.gz -C /var/www $APP_NAME
# Keep only last 7 days of backups
find \$BACKUP_DIR -name "*.sql" -mtime +7 -delete
find \$BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
echo "Backup completed: \$TIMESTAMP"
EOF
    
    sudo chmod +x /usr/local/bin/indo-advisory-backup.sh
    
    # Setup daily backup cron
    (crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/indo-advisory-backup.sh") | crontab -
    
    log "Backup system setup completed"
}
# Health check
health_check() {
    log "Performing health check..."
    
    sleep 5  # Wait for application to start
    
    # Check if application is responding
    if curl -f http://localhost:3000 > /dev/null 2>&1; then
        log "✓ Application is responding"
    else
        error "✗ Application is not responding"
        pm2 logs $APP_NAME --lines 20
        exit 1
    fi
    
    # Check database connection
    cd $APP_DIR
    if npm run db:check > /dev/null 2>&1; then
        log "✓ Database connection successful"
    else
        warning "⚠ Database connection check failed"
    fi
    
    log "Health check completed"
}
# Main deployment function
deploy() {
    local environment=${1:-production}
    
    log "Starting deployment for $environment environment..."
    
    check_root
    install_dependencies
    setup_database
    setup_app_directory
    deploy_code
    install_node_dependencies
    setup_environment
    run_migrations
    setup_nginx
    
    if [ "$environment" = "production" ]; then
        setup_ssl
        setup_firewall
        setup_fail2ban
        setup_backup
    fi
    
    start_application
    health_check
    
    log "🎉 Deployment completed successfully!"
    log "🌐 Application available at: http://your-domain.com"
    log "🔐 Admin panel: http://your-domain.com/admin"
    log "📊 PM2 status: pm2 status"
    log "📋 Logs: pm2 logs $APP_NAME"
    
    info "Next steps:"
    info "1. Update DNS records to point to this server"
    info "2. Test SSL certificate renewal: sudo certbot renew --dry-run"
    info "3. Monitor application logs: pm2 logs"
    info "4. Setup monitoring and alerting"
}
# Script execution
case "${1:-production}" in
    production|staging)
        deploy $1
        ;;
    *)
        echo "Usage: $0 [production|staging]"
        exit 1
        ;;
esac