baic_dashboard/deploy.sh
michael 4d918ed037 Fix Vite environment variable loading during production build
Updated deploy.sh to copy .env file to frontend directory before building, ensuring Vite can access environment variables (including VITE_REDIRECT_URI) during the production build process. The temporary .env is cleaned up after build completes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 09:30:44 -06:00

491 lines
14 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
################################################################################
# BAIC Dashboard Deployment Script
#
# This script automates the deployment of the BAIC Dashboard application
# on an Ubuntu server with Apache and systemd.
#
# Prerequisites:
# - Repository cloned to /opt/baic_dashboard
# - .env file configured in repository root
# - Run this script from /opt/baic_dashboard directory
# - Execute with sudo/root privileges
#
# Usage: sudo bash deploy.sh
################################################################################
set -e # Exit on any error
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Expected deployment directory
EXPECTED_DIR="/opt/baic_dashboard"
SERVICE_NAME="baic-dashboard"
SERVICE_USER="www-data"
################################################################################
# Helper Functions
################################################################################
print_header() {
echo -e "\n${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}\n"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_error() {
echo -e "${RED}✗ ERROR: $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠ WARNING: $1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
exit_with_error() {
print_error "$1"
exit 1
}
################################################################################
# Pre-flight Checks
################################################################################
print_header "Pre-flight Checks"
# Check if running as root
if [[ $EUID -ne 0 ]]; then
exit_with_error "This script must be run as root (use sudo)"
fi
print_success "Running as root"
# Check if we're in the correct directory
CURRENT_DIR=$(pwd)
if [[ "$CURRENT_DIR" != "$EXPECTED_DIR" ]]; then
exit_with_error "Script must be run from $EXPECTED_DIR (currently in $CURRENT_DIR)"
fi
print_success "Running from correct directory: $EXPECTED_DIR"
# Check for required commands
REQUIRED_COMMANDS=("python3" "npm" "systemctl")
for cmd in "${REQUIRED_COMMANDS[@]}"; do
if ! command -v $cmd &> /dev/null; then
exit_with_error "$cmd is not installed. Please install it first."
fi
print_success "$cmd is installed"
done
# Check if .env file exists
if [[ ! -f ".env" ]]; then
exit_with_error ".env file not found in current directory. Please create it before running this script."
fi
print_success ".env file found"
# Check if apache2 is installed (warn if not, but don't fail)
if ! command -v apache2 &> /dev/null; then
print_warning "apache2 is not installed. You'll need to install and configure it manually."
else
print_success "apache2 is installed"
fi
################################################################################
# Backend Setup
################################################################################
print_header "Backend Setup"
# Create Python virtual environment
print_info "Creating Python virtual environment..."
if [[ -d "venv" ]]; then
print_warning "Virtual environment already exists. Removing and recreating..."
rm -rf venv
fi
python3 -m venv venv
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to create virtual environment"
fi
print_success "Virtual environment created"
# Activate virtual environment and install dependencies
print_info "Installing Python dependencies from requirements.txt..."
source venv/bin/activate
if [[ ! -f "backend/requirements.txt" ]]; then
exit_with_error "backend/requirements.txt not found"
fi
pip install --upgrade pip > /dev/null 2>&1
pip install -r backend/requirements.txt
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to install Python dependencies"
fi
print_success "Python dependencies installed"
# Test that Flask can be imported
python3 -c "import flask" 2>/dev/null
if [[ $? -ne 0 ]]; then
exit_with_error "Flask installation verification failed"
fi
print_success "Flask installation verified"
deactivate
# Set ownership to www-data
print_info "Setting ownership to $SERVICE_USER..."
chown -R $SERVICE_USER:$SERVICE_USER venv
chown -R $SERVICE_USER:$SERVICE_USER backend
print_success "Ownership set to $SERVICE_USER"
################################################################################
# Frontend Build
################################################################################
print_header "Frontend Build"
# Check if frontend directory exists
if [[ ! -d "frontend" ]]; then
exit_with_error "frontend directory not found"
fi
cd frontend
# Install npm dependencies
print_info "Installing npm dependencies..."
npm install
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to install npm dependencies"
fi
print_success "npm dependencies installed"
# Copy .env file to frontend directory for Vite to read during build
print_info "Copying .env to frontend directory for build..."
cp ../.env ./.env
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to copy .env file"
fi
print_success ".env file copied"
# Build frontend
print_info "Building frontend for production (this may take a minute)..."
npm run build
if [[ $? -ne 0 ]]; then
exit_with_error "Frontend build failed"
fi
# Remove .env from frontend directory (cleanup)
print_info "Cleaning up temporary .env file..."
rm -f ./.env
print_success "Cleanup complete"
# Verify dist directory was created
if [[ ! -d "dist" ]]; then
exit_with_error "Build completed but dist/ directory not found"
fi
print_success "Frontend built successfully"
cd ..
################################################################################
# Frontend Deployment
################################################################################
print_header "Frontend Deployment"
# Prompt user for frontend deployment path
echo -e "${BLUE}Please enter the full path where the frontend files should be deployed${NC}"
echo -e "${BLUE}(e.g., /var/www/html/dashboard or /var/www/mysite.com/dashboard)${NC}"
read -p "Deployment path: " FRONTEND_DEPLOY_PATH
# Validate input
if [[ -z "$FRONTEND_DEPLOY_PATH" ]]; then
exit_with_error "No deployment path provided"
fi
# Create directory if it doesn't exist
if [[ ! -d "$FRONTEND_DEPLOY_PATH" ]]; then
print_info "Creating directory: $FRONTEND_DEPLOY_PATH"
mkdir -p "$FRONTEND_DEPLOY_PATH"
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to create deployment directory"
fi
fi
# Copy frontend files
print_info "Copying frontend files to $FRONTEND_DEPLOY_PATH..."
cp -r frontend/dist/* "$FRONTEND_DEPLOY_PATH/"
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to copy frontend files"
fi
print_success "Frontend files copied"
# Set ownership and permissions
print_info "Setting ownership and permissions..."
chown -R $SERVICE_USER:$SERVICE_USER "$FRONTEND_DEPLOY_PATH"
find "$FRONTEND_DEPLOY_PATH" -type d -exec chmod 755 {} \;
find "$FRONTEND_DEPLOY_PATH" -type f -exec chmod 644 {} \;
print_success "Ownership and permissions set"
################################################################################
# Systemd Service Creation
################################################################################
print_header "Systemd Service Setup"
# Read BACKEND_PORT from .env or use default
BACKEND_PORT=$(grep "^BACKEND_PORT=" .env | cut -d'=' -f2 | tr -d ' ')
if [[ -z "$BACKEND_PORT" ]]; then
BACKEND_PORT="5001"
print_warning "BACKEND_PORT not found in .env, using default: 5001"
else
print_info "Using BACKEND_PORT from .env: $BACKEND_PORT"
fi
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
print_info "Creating systemd service file: $SERVICE_FILE"
cat > "$SERVICE_FILE" << EOF
[Unit]
Description=BAIC Dashboard Backend Service
After=network.target
[Service]
Type=simple
User=$SERVICE_USER
Group=$SERVICE_USER
WorkingDirectory=$EXPECTED_DIR/backend
EnvironmentFile=$EXPECTED_DIR/.env
ExecStart=$EXPECTED_DIR/venv/bin/python app.py
# Restart policy
Restart=always
RestartSec=10
# Security settings
NoNewPrivileges=true
PrivateTmp=true
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=$SERVICE_NAME
[Install]
WantedBy=multi-user.target
EOF
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to create systemd service file"
fi
print_success "Systemd service file created"
################################################################################
# Service Management
################################################################################
print_header "Service Management"
# Reload systemd daemon
print_info "Reloading systemd daemon..."
systemctl daemon-reload
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to reload systemd daemon"
fi
print_success "Systemd daemon reloaded"
# Enable service
print_info "Enabling service to start on boot..."
systemctl enable $SERVICE_NAME
if [[ $? -ne 0 ]]; then
exit_with_error "Failed to enable service"
fi
print_success "Service enabled"
# Start service
print_info "Starting service..."
systemctl start $SERVICE_NAME
if [[ $? -ne 0 ]]; then
print_error "Failed to start service. Check logs with: journalctl -u $SERVICE_NAME -n 50"
exit 1
fi
print_success "Service started"
# Wait a moment for service to initialize
sleep 2
# Check service status
print_info "Checking service status..."
if systemctl is-active --quiet $SERVICE_NAME; then
print_success "Service is running"
echo ""
systemctl status $SERVICE_NAME --no-pager -l
else
print_error "Service failed to start properly"
print_info "Showing recent logs:"
journalctl -u $SERVICE_NAME -n 20 --no-pager
exit 1
fi
################################################################################
# Apache Configuration Generation
################################################################################
print_header "Apache Configuration"
# Get domain and base path from .env
DOMAIN=$(grep "^DOMAIN=" .env | cut -d'=' -f2 | tr -d ' ')
BASE_PATH=$(grep "^BASE_PATH=" .env | cut -d'=' -f2 | tr -d ' ')
if [[ -z "$DOMAIN" ]]; then
DOMAIN="yourdomain.com"
print_warning "DOMAIN not found in .env, using placeholder in config"
fi
if [[ -z "$BASE_PATH" ]]; then
BASE_PATH="/dashboard/"
print_warning "BASE_PATH not found in .env, using default: /dashboard/"
fi
# Remove trailing slash from BASE_PATH for cleaner config
BASE_PATH_NO_SLASH=${BASE_PATH%/}
APACHE_CONFIG_FILE="$EXPECTED_DIR/apache-config.conf"
print_info "Generating Apache configuration: $APACHE_CONFIG_FILE"
cat > "$APACHE_CONFIG_FILE" << EOF
# Apache Configuration for BAIC Dashboard
#
# Add this configuration to your Apache virtual host file
# (e.g., /etc/apache2/sites-available/000-default.conf or your custom site config)
#
# Required Apache modules (enable with a2enmod):
# - proxy
# - proxy_http
# - headers
# - rewrite
#
# Enable modules:
# sudo a2enmod proxy proxy_http headers rewrite
# sudo systemctl restart apache2
<VirtualHost *:443>
ServerName $DOMAIN
# SSL Configuration (adjust paths to your certificates)
# SSLEngine on
# SSLCertificateFile /etc/letsencrypt/live/$DOMAIN/fullchain.pem
# SSLCertificateKeyFile /etc/letsencrypt/live/$DOMAIN/privkey.pem
# Frontend static files
Alias $BASE_PATH_NO_SLASH $FRONTEND_DEPLOY_PATH
<Directory $FRONTEND_DEPLOY_PATH>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# Handle client-side routing (React Router)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase $BASE_PATH_NO_SLASH/
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . $BASE_PATH_NO_SLASH/index.html [L]
</IfModule>
</Directory>
# Backend API reverse proxy
ProxyPreserveHost On
ProxyTimeout 300
<Location $BASE_PATH_NO_SLASH/back/api>
ProxyPass http://localhost:$BACKEND_PORT/api
ProxyPassReverse http://localhost:$BACKEND_PORT/api
# Add headers for proper proxying
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
</Location>
# Error and Access logs
ErrorLog \${APACHE_LOG_DIR}/${SERVICE_NAME}-error.log
CustomLog \${APACHE_LOG_DIR}/${SERVICE_NAME}-access.log combined
</VirtualHost>
# Optional: Redirect HTTP to HTTPS
<VirtualHost *:80>
ServerName $DOMAIN
Redirect permanent / https://$DOMAIN/
</VirtualHost>
EOF
if [[ $? -ne 0 ]]; then
print_error "Failed to create Apache configuration file"
else
print_success "Apache configuration file created"
fi
################################################################################
# Deployment Complete
################################################################################
print_header "Deployment Complete!"
echo -e "${GREEN}✓ Backend virtual environment created and dependencies installed${NC}"
echo -e "${GREEN}✓ Frontend built and deployed to: $FRONTEND_DEPLOY_PATH${NC}"
echo -e "${GREEN}✓ Systemd service created and started: $SERVICE_NAME${NC}"
echo -e "${GREEN}✓ Apache configuration generated: $APACHE_CONFIG_FILE${NC}"
echo ""
print_header "Next Steps"
echo -e "${YELLOW}1. Review the Apache configuration:${NC}"
echo -e " cat $APACHE_CONFIG_FILE"
echo ""
echo -e "${YELLOW}2. Enable required Apache modules:${NC}"
echo -e " sudo a2enmod proxy proxy_http headers rewrite"
echo ""
echo -e "${YELLOW}3. Add the configuration to your Apache virtual host:${NC}"
echo -e " - Edit: /etc/apache2/sites-available/your-site.conf"
echo -e " - Or copy: sudo cp $APACHE_CONFIG_FILE /etc/apache2/sites-available/${SERVICE_NAME}.conf"
echo -e " - Enable: sudo a2ensite ${SERVICE_NAME}"
echo ""
echo -e "${YELLOW}4. Test Apache configuration:${NC}"
echo -e " sudo apache2ctl configtest"
echo ""
echo -e "${YELLOW}5. Reload Apache:${NC}"
echo -e " sudo systemctl reload apache2"
echo ""
echo -e "${YELLOW}6. Configure SSL/TLS certificates (if not already done):${NC}"
echo -e " sudo apt install certbot python3-certbot-apache"
echo -e " sudo certbot --apache -d $DOMAIN"
echo ""
print_header "Useful Commands"
echo -e "${BLUE}Service Management:${NC}"
echo -e " sudo systemctl status $SERVICE_NAME # Check service status"
echo -e " sudo systemctl restart $SERVICE_NAME # Restart service"
echo -e " sudo systemctl stop $SERVICE_NAME # Stop service"
echo -e " sudo journalctl -u $SERVICE_NAME -f # View live logs"
echo -e " sudo journalctl -u $SERVICE_NAME -n 100 # View last 100 log lines"
echo ""
print_success "Deployment script completed successfully!"
exit 0