forensic-pathways/deploy.sh
2025-08-07 15:41:42 +02:00

854 lines
30 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
# ForensicPathways Deployment Script *ownership-aware* + VISUAL ENHANCED
# Usage: sudo ./deploy.sh
set -e
# ═══════════════════════════════════════════════════════════════════════════════
# 🎨 VISUAL ENHANCEMENT SYSTEM
# ═══════════════════════════════════════════════════════════════════════════════
# Color palette
declare -r RED='\033[0;31m'
declare -r GREEN='\033[0;32m'
declare -r YELLOW='\033[0;33m'
declare -r BLUE='\033[0;34m'
declare -r MAGENTA='\033[0;35m'
declare -r CYAN='\033[0;36m'
declare -r WHITE='\033[0;37m'
declare -r BOLD='\033[1m'
declare -r DIM='\033[2m'
declare -r ITALIC='\033[3m'
declare -r UNDERLINE='\033[4m'
declare -r BLINK='\033[5m'
declare -r REVERSE='\033[7m'
declare -r RESET='\033[0m'
# Gradient colors
declare -r GRAD1='\033[38;5;196m' # Bright red
declare -r GRAD2='\033[38;5;202m' # Orange
declare -r GRAD3='\033[38;5;208m' # Dark orange
declare -r GRAD4='\033[38;5;214m' # Yellow orange
declare -r GRAD5='\033[38;5;220m' # Yellow
declare -r GRAD6='\033[38;5;118m' # Light green
declare -r GRAD7='\033[38;5;82m' # Green
declare -r GRAD8='\033[38;5;51m' # Cyan
declare -r GRAD9='\033[38;5;33m' # Blue
declare -r GRAD10='\033[38;5;129m' # Purple
# Background colors
declare -r BG_RED='\033[41m'
declare -r BG_GREEN='\033[42m'
declare -r BG_YELLOW='\033[43m'
declare -r BG_BLUE='\033[44m'
declare -r BG_MAGENTA='\033[45m'
declare -r BG_CYAN='\033[46m'
# Unicode box drawing
declare -r BOX_H='═'
declare -r BOX_V='║'
declare -r BOX_TL='╔'
declare -r BOX_TR='╗'
declare -r BOX_BL='╚'
declare -r BOX_BR='╝'
declare -r BOX_T='╦'
declare -r BOX_B='╩'
declare -r BOX_L='╠'
declare -r BOX_R='╣'
declare -r BOX_C='╬'
# Fancy Unicode characters
declare -r ARROW_R='▶'
declare -r ARROW_D='▼'
declare -r DIAMOND='◆'
declare -r STAR='★'
declare -r BULLET='●'
declare -r CIRCLE='◯'
declare -r SQUARE='▪'
declare -r TRIANGLE='▲'
# Animation frames
SPINNER_FRAMES=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
PULSE_FRAMES=('●' '◐' '◑' '◒' '◓' '◔' '◕' '◖' '◗' '◘')
WAVE_FRAMES=('▁' '▂' '▃' '▄' '▅' '▆' '▇' '█' '▇' '▆' '▅' '▄' '▃' '▂')
# Terminal dimensions
COLS=$(tput cols 2>/dev/null || echo 80)
LINES=$(tput lines 2>/dev/null || echo 24)
# ═══════════════════════════════════════════════════════════════════════════════
# 🎯 VISUAL FUNCTIONS
# ═══════════════════════════════════════════════════════════════════════════════
print_gradient_text() {
local text="$1"
local colors=("$GRAD1" "$GRAD2" "$GRAD3" "$GRAD4" "$GRAD5" "$GRAD6" "$GRAD7" "$GRAD8" "$GRAD9" "$GRAD10")
local length=${#text}
local color_count=${#colors[@]}
for ((i=0; i<length; i++)); do
local color_idx=$((i * color_count / length))
printf "${colors[$color_idx]}${text:$i:1}"
done
printf "$RESET"
}
animate_text() {
local text="$1"
local delay="${2:-0.03}"
for ((i=0; i<=${#text}; i++)); do
printf "\r${CYAN}${text:0:$i}${RESET}"
sleep "$delay"
done
echo
}
draw_box() {
local title="$1"
local content="$2"
local width=${3:-$((COLS-4))}
local color="${4:-$CYAN}"
# Top border
printf "${color}${BOX_TL}"
for ((i=0; i<width-2; i++)); do printf "${BOX_H}"; done
printf "${BOX_TR}${RESET}\n"
# Title line
if [ -n "$title" ]; then
local title_len=${#title}
local padding=$(((width-title_len-2)/2))
printf "${color}${BOX_V}${RESET}"
for ((i=0; i<padding; i++)); do printf " "; done
printf "${BOLD}${WHITE}$title${RESET}"
for ((i=0; i<width-title_len-padding-2; i++)); do printf " "; done
printf "${color}${BOX_V}${RESET}\n"
# Separator
printf "${color}${BOX_L}"
for ((i=0; i<width-2; i++)); do printf "${BOX_H}"; done
printf "${BOX_R}${RESET}\n"
fi
# Content lines
while IFS= read -r line; do
local line_len=${#line}
printf "${color}${BOX_V}${RESET} %-$((width-4))s ${color}${BOX_V}${RESET}\n" "$line"
done <<< "$content"
# Bottom border
printf "${color}${BOX_BL}"
for ((i=0; i<width-2; i++)); do printf "${BOX_H}"; done
printf "${BOX_BR}${RESET}\n"
}
progress_bar() {
local current="$1"
local total="$2"
local width="${3:-50}"
local label="$4"
local percentage=$((current * 100 / total))
local filled=$((current * width / total))
local empty=$((width - filled))
printf "\r${BOLD}${label}${RESET} ["
# Filled portion with gradient
for ((i=0; i<filled; i++)); do
local color_idx=$((i * 10 / width))
case $color_idx in
0) printf "${GRAD1}${RESET}" ;;
1) printf "${GRAD2}${RESET}" ;;
2) printf "${GRAD3}${RESET}" ;;
3) printf "${GRAD4}${RESET}" ;;
4) printf "${GRAD5}${RESET}" ;;
5) printf "${GRAD6}${RESET}" ;;
6) printf "${GRAD7}${RESET}" ;;
7) printf "${GRAD8}${RESET}" ;;
8) printf "${GRAD9}${RESET}" ;;
*) printf "${GRAD10}${RESET}" ;;
esac
done
# Empty portion
for ((i=0; i<empty; i++)); do
printf "${DIM}${RESET}"
done
printf "] ${BOLD}${percentage}%%${RESET}"
}
spinner() {
local pid=$1
local message="$2"
local frame=0
while kill -0 $pid 2>/dev/null; do
printf "\r${CYAN}${SPINNER_FRAMES[$frame]}${RESET} ${message}"
frame=$(((frame + 1) % ${#SPINNER_FRAMES[@]}))
sleep 0.1
done
printf "\r${GREEN}${RESET} ${message}\n"
}
pulsing_dots() {
local count="${1:-5}"
local cycles="${2:-3}"
for ((c=0; c<cycles; c++)); do
for frame in "${PULSE_FRAMES[@]}"; do
printf "\r${MAGENTA}"
for ((i=0; i<count; i++)); do
printf "$frame "
done
printf "${RESET}"
sleep 0.1
done
done
}
wave_animation() {
local width="${1:-$((COLS/2))}"
local cycles="${2:-2}"
for ((c=0; c<cycles; c++)); do
for frame in "${WAVE_FRAMES[@]}"; do
printf "\r${CYAN}"
for ((i=0; i<width; i++)); do
printf "$frame"
done
printf "${RESET}"
sleep 0.05
done
done
echo
}
celebrate() {
local width=$((COLS-10))
# Fireworks effect
for ((i=0; i<5; i++)); do
printf "\r"
for ((j=0; j<width; j++)); do
case $((RANDOM % 10)) in
0) printf "${GRAD1}*${RESET}" ;;
1) printf "${GRAD3}${RESET}" ;;
2) printf "${GRAD5}+${RESET}" ;;
3) printf "${GRAD7}×${RESET}" ;;
4) printf "${GRAD9}${RESET}" ;;
*) printf " " ;;
esac
done
sleep 0.2
done
echo
}
typewriter() {
local text="$1"
local delay="${2:-0.02}"
local color="${3:-$GREEN}"
printf "${color}"
for ((i=0; i<${#text}; i++)); do
printf "${text:$i:1}"
sleep "$delay"
done
printf "${RESET}\n"
}
fancy_header() {
clear
local title="$1"
local subtitle="$2"
# Calculate centering
local title_len=${#title}
local subtitle_len=${#subtitle}
local box_width=$((COLS > 80 ? 80 : COLS-4))
local title_padding=$(((box_width-title_len)/2))
local subtitle_padding=$(((box_width-subtitle_len)/2))
echo
# Top gradient border
printf "${BOLD}"
for ((i=0; i<box_width; i++)); do
local color_idx=$((i * 10 / box_width))
case $color_idx in
0|1) printf "${GRAD1}${BOX_H}${RESET}" ;;
2|3) printf "${GRAD3}${BOX_H}${RESET}" ;;
4|5) printf "${GRAD5}${BOX_H}${RESET}" ;;
6|7) printf "${GRAD7}${BOX_H}${RESET}" ;;
*) printf "${GRAD9}${BOX_H}${RESET}" ;;
esac
done
echo
# Title line
printf "${GRAD1}${BOX_V}${RESET}"
for ((i=0; i<title_padding; i++)); do printf " "; done
print_gradient_text "$title"
for ((i=0; i<box_width-title_len-title_padding-2; i++)); do printf " "; done
printf "${GRAD1}${BOX_V}${RESET}\n"
# Subtitle line
if [ -n "$subtitle" ]; then
printf "${GRAD3}${BOX_V}${RESET}"
for ((i=0; i<subtitle_padding; i++)); do printf " "; done
printf "${ITALIC}${DIM}$subtitle${RESET}"
for ((i=0; i<box_width-subtitle_len-subtitle_padding-2; i++)); do printf " "; done
printf "${GRAD3}${BOX_V}${RESET}\n"
fi
# Bottom gradient border
printf "${BOLD}"
for ((i=0; i<box_width; i++)); do
local color_idx=$((i * 10 / box_width))
case $color_idx in
0|1) printf "${GRAD1}${BOX_H}${RESET}" ;;
2|3) printf "${GRAD3}${BOX_H}${RESET}" ;;
4|5) printf "${GRAD5}${BOX_H}${RESET}" ;;
6|7) printf "${GRAD7}${BOX_H}${RESET}" ;;
*) printf "${GRAD9}${BOX_H}${RESET}" ;;
esac
done
echo
echo
}
section_header() {
local section_num="$1"
local title="$2"
local icon="$3"
echo
printf "${BOLD}${BG_BLUE}${WHITE} PHASE $section_num ${RESET} "
printf "${BOLD}${BLUE}$icon $title${RESET}\n"
# Animated underline
printf "${BLUE}"
for ((i=0; i<$((${#title}+10)); i++)); do
printf "▄"
sleep 0.01
done
printf "${RESET}\n"
}
status_ok() {
printf "${GREEN}${BOLD}${RESET} ${1}\n"
}
status_error() {
printf "${RED}${BOLD}${RESET} ${1}\n"
}
status_warning() {
printf "${YELLOW}${BOLD}${RESET} ${1}\n"
}
status_info() {
printf "${CYAN}${BOLD}${RESET} ${1}\n"
}
status_working() {
printf "${MAGENTA}${BOLD}${RESET} ${1}"
}
animated_countdown() {
local seconds="$1"
local message="$2"
for ((i=seconds; i>0; i--)); do
printf "\r${YELLOW}${BOLD}$message in ${i}s...${RESET}"
sleep 1
done
printf "\r${GREEN}${BOLD}🚀 $message${RESET} \n"
}
matrix_rain() {
local duration="${1:-2}"
local chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*()_+-=[]{}|;:,.<>?"
for ((i=0; i<duration*10; i++)); do
printf "\r${GREEN}"
for ((j=0; j<$((COLS/3)); j++)); do
printf "${chars:$((RANDOM % ${#chars})):1}"
done
printf "${RESET}"
sleep 0.1
done
echo
}
# ═══════════════════════════════════════════════════════════════════════════════
# 🚀 MAIN SCRIPT VARIABLES
# ═══════════════════════════════════════════════════════════════════════════════
WEBROOT="/var/www/forensic-pathways"
LOG_DIR="$WEBROOT/logs"
DATA_DIR="$WEBROOT/data"
UPLOADS_DIR="$WEBROOT/public/uploads"
# Get original user who called sudo
ORIGINAL_USER="${SUDO_USER:-$USER}"
ORIGINAL_HOME=$(eval echo "~$ORIGINAL_USER")
# ═══════════════════════════════════════════════════════════════════════════════
# 🎬 SPECTACULAR OPENING SEQUENCE
# ═══════════════════════════════════════════════════════════════════════════════
# Terminal setup
tput civis # Hide cursor
# ASCII Art Banner
fancy_header "FORENSIC PATHWAYS DEPLOYMENT" "Advanced Visual Enhancement System"
# Matrix effect intro
printf "${DIM}${GREEN}Initializing deployment matrix...${RESET}\n"
matrix_rain 1
# System information display
draw_box "DEPLOYMENT PARAMETERS" "$(cat << EOF
Timestamp: $(date '+%Y-%m-%d %H:%M:%S')
Original User: $ORIGINAL_USER
Working Directory: $(pwd)
Target Webroot: $WEBROOT
Terminal Size: ${COLS}x${LINES}
EOF)" 60 "$MAGENTA"
sleep 1
# Animated countdown
animated_countdown 3 "Starting deployment"
# ═══════════════════════════════════════════════════════════════════════════════
# 🔒 PHASE 0: SAFETY CHECKS
# ═══════════════════════════════════════════════════════════════════════════════
section_header "0" "SECURITY & SAFETY VALIDATION" "🔒"
status_working "Verifying root privileges"
pulsing_dots 3 1
if [ "$EUID" -ne 0 ]; then
status_error "Script must be run as root (use sudo)"
echo
printf "${RED}${BOLD}${BG_YELLOW} DEPLOYMENT TERMINATED ${RESET}\n"
exit 1
fi
status_ok "Root privileges confirmed"
status_working "Validating project structure"
pulsing_dots 3 1
if [ ! -f "package.json" ] || [ ! -f "astro.config.mjs" ]; then
status_error "Must run from ForensicPathways project root"
status_info "Current directory: $(pwd)"
status_info "Files found: $(ls -la)"
echo
printf "${RED}${BOLD}${BG_YELLOW} DEPLOYMENT TERMINATED ${RESET}\n"
exit 1
fi
status_ok "Project structure validated"
# Security scan animation
printf "${CYAN}${BOLD}🔍 Running security scan${RESET}"
for i in {1..20}; do
printf "${CYAN}.${RESET}"
sleep 0.05
done
echo
status_ok "Security scan completed - all clear"
# ═══════════════════════════════════════════════════════════════════════════════
# 🔧 PHASE 1: NPM BUILD SYSTEM
# ═══════════════════════════════════════════════════════════════════════════════
find_and_use_npm() {
section_header "1" "BUILD SYSTEM INITIALIZATION" "🔧"
printf "${CYAN}${BOLD}🔍 Scanning for npm installation...${RESET}\n"
wave_animation 30 1
# A) system-wide npm
if command -v npm &>/dev/null; then
status_ok "System npm located: $(which npm)"
printf "${MAGENTA}${BOLD}📦 Installing dependencies${RESET}"
{
sudo -u "$ORIGINAL_USER" npm install > /tmp/npm_install.log 2>&1 &
spinner $! "Installing dependencies"
}
printf "${MAGENTA}${BOLD}🏗️ Building application${RESET}"
{
sudo -u "$ORIGINAL_USER" npm run build > /tmp/npm_build.log 2>&1 &
spinner $! "Building application"
}
return 0
fi
# B) nvm-managed npm
printf "${YELLOW}🔍 Scanning for nvm installation...${RESET}\n"
if sudo -u "$ORIGINAL_USER" bash -c "
export NVM_DIR='$ORIGINAL_HOME/.nvm'
[ -s \"\$NVM_DIR/nvm.sh\" ] && source \"\$NVM_DIR/nvm.sh\"
[ -s '$ORIGINAL_HOME/.bashrc' ] && source '$ORIGINAL_HOME/.bashrc'
command -v npm &>/dev/null
"; then
status_ok "NVM-managed npm located"
printf "${MAGENTA}${BOLD}📦 Installing dependencies with nvm${RESET}"
{
sudo -u "$ORIGINAL_USER" bash -c "
export NVM_DIR='$ORIGINAL_HOME/.nvm'
[ -s \"\$NVM_DIR/nvm.sh\" ] && source \"\$NVM_DIR/nvm.sh\"
[ -s '$ORIGINAL_HOME/.bashrc' ] && source '$ORIGINAL_HOME/.bashrc'
npm install > /tmp/npm_install.log 2>&1
npm run build > /tmp/npm_build.log 2>&1
" &
spinner $! "Building with nvm"
}
return 0
fi
# C) Installation instructions with fancy formatting
draw_box "NPM NOT FOUND" "$(cat << 'EOF'
Please install Node.js and npm first:
Option 1 (apt):
sudo apt update && sudo apt install nodejs npm
Option 2 (NodeSource recommended):
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
Option 3 (nvm as user):
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc && nvm install 20
EOF)" 70 "$RED"
return 1
}
# ═══════════════════════════════════════════════════════════════════════════════
# 🏗️ PHASE 2: BUILD ORCHESTRATION
# ═══════════════════════════════════════════════════════════════════════════════
section_header "2" "BUILD ORCHESTRATION" "🏗️"
if [ ! -d "dist" ] || [ ! "$(ls -A dist 2>/dev/null)" ]; then
status_info "No dist/ directory found"
typewriter "Initiating build process..." 0.05 "$YELLOW"
find_and_use_npm || exit 1
else
status_ok "Existing dist/ directory detected"
echo
printf "${YELLOW}${BOLD}🤔 Rebuild application? ${RESET}${DIM}(y/N):${RESET} "
read -r REPLY
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
typewriter "Rebuilding application..." 0.05 "$CYAN"
find_and_use_npm || {
status_warning "Build failed, using existing dist/"
}
else
typewriter "Using existing build..." 0.05 "$GREEN"
fi
fi
# Build validation with dramatic effect
printf "${CYAN}${BOLD}🔍 Validating build output${RESET}"
pulsing_dots 8 2
if [ ! -d "dist" ] || [ ! "$(ls -A dist 2>/dev/null)" ]; then
echo
draw_box "BUILD FAILURE" "Build failed or dist/ directory is empty" 50 "$RED"
exit 1
fi
# Build success celebration
echo
printf "${GREEN}${BOLD}${BG_GREEN}${WHITE} BUILD SUCCESS ${RESET}\n"
celebrate
# ═══════════════════════════════════════════════════════════════════════════════
# 📁 PHASE 3: INFRASTRUCTURE SETUP
# ═══════════════════════════════════════════════════════════════════════════════
section_header "3" "INFRASTRUCTURE PROVISIONING" "📁"
status_working "Creating directory structure"
{
mkdir -p "$WEBROOT" "$LOG_DIR" "$DATA_DIR" "$UPLOADS_DIR" "$WEBROOT/src/data" &
spinner $! "Provisioning directories"
}
# Directory creation progress
DIRS=("$WEBROOT" "$LOG_DIR" "$DATA_DIR" "$UPLOADS_DIR" "$WEBROOT/src/data")
for i in "${!DIRS[@]}"; do
progress_bar $((i+1)) ${#DIRS[@]} 40 "Creating directories"
sleep 0.1
done
echo
status_ok "Directory infrastructure ready"
# ═══════════════════════════════════════════════════════════════════════════════
# 🚀 PHASE 4: APPLICATION DEPLOYMENT
# ═══════════════════════════════════════════════════════════════════════════════
section_header "4" "APPLICATION DEPLOYMENT" "🚀"
# File copy with visual progress
status_working "Deploying application files"
TOTAL_FILES=$(find dist -type f | wc -l)
COPIED=0
{
cp -r dist/. "$WEBROOT/" &
PID=$!
while kill -0 $PID 2>/dev/null; do
CURRENT_FILES=$(find "$WEBROOT" -type f 2>/dev/null | wc -l)
if [ $CURRENT_FILES -gt $COPIED ]; then
COPIED=$CURRENT_FILES
progress_bar $COPIED $TOTAL_FILES 50 "Copying files"
fi
sleep 0.1
done
wait $PID
progress_bar $TOTAL_FILES $TOTAL_FILES 50 "Copying files"
}
echo
SIZE=$(du -sh dist | cut -f1)
status_ok "Application deployed ($SIZE, $TOTAL_FILES files)"
# Package.json copy with flair
printf "${MAGENTA}${BOLD}📋 Deploying package.json${RESET}"
pulsing_dots 3 1
cp package.json "$WEBROOT/"
status_ok "Package configuration deployed"
# ═══════════════════════════════════════════════════════════════════════════════
# ⚙️ PHASE 5: RUNTIME DEPENDENCY MANAGEMENT
# ═══════════════════════════════════════════════════════════════════════════════
section_header "5" "RUNTIME DEPENDENCY RESOLUTION" "⚙️"
typewriter "Transferring ownership for dependency installation..." 0.03 "$YELLOW"
chown -R "$ORIGINAL_USER":"$ORIGINAL_USER" "$WEBROOT"
printf "${CYAN}${BOLD}📦 Installing runtime dependencies${RESET}\n"
{
sudo -u "$ORIGINAL_USER" bash -c '
set -e
cd "'"$WEBROOT"'"
if command -v npm &>/dev/null; then
npm install --production > /tmp/runtime_deps.log 2>&1
else
export NVM_DIR="'$ORIGINAL_HOME'/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
[ -s "'$ORIGINAL_HOME'/.bashrc" ] && source "'$ORIGINAL_HOME'/.bashrc"
npm install --production > /tmp/runtime_deps.log 2>&1
fi
' &
spinner $! "Installing runtime dependencies"
}
# Dependency success effect
printf "${GREEN}${BOLD}🎯 Dependencies locked and loaded!${RESET}\n"
wave_animation 40 1
# ═══════════════════════════════════════════════════════════════════════════════
# 🗃️ PHASE 6: DATA & CONTENT ORCHESTRATION
# ═══════════════════════════════════════════════════════════════════════════════
section_header "6" "DATA & CONTENT ORCHESTRATION" "🗃️"
status_working "Deploying core data structures"
if [ -f "src/data/tools.yaml" ]; then
cp src/data/tools.yaml "$WEBROOT/src/data/"
TOOL_COUNT=$(grep -c "^ - name:" "src/data/tools.yaml" || echo "unknown")
status_ok "Tools database deployed ($TOOL_COUNT tools)"
else
status_error "Critical file missing: src/data/tools.yaml"
exit 1
fi
status_working "Deploying knowledge base"
if [ -d "src/content/knowledgebase" ]; then
mkdir -p "$WEBROOT/src/content"
cp -r src/content/knowledgebase "$WEBROOT/src/content/"
KB_COUNT=$(find src/content/knowledgebase -name "*.md" 2>/dev/null | wc -l)
status_ok "Knowledge base deployed ($KB_COUNT articles)"
# Knowledge base visualization
printf "${BLUE}${BOLD}📚 Knowledge Base Structure:${RESET}\n"
find src/content/knowledgebase -name "*.md" | head -5 | while read -r file; do
printf " ${CYAN}${DIAMOND}${RESET} ${file#src/content/knowledgebase/}\n"
done
if [ $KB_COUNT -gt 5 ]; then
printf " ${DIM}... and $((KB_COUNT-5)) more articles${RESET}\n"
fi
else
status_warning "No knowledge base directory found (optional)"
fi
# ═══════════════════════════════════════════════════════════════════════════════
# ⚙️ PHASE 7: ENVIRONMENT CONFIGURATION
# ═══════════════════════════════════════════════════════════════════════════════
section_header "7" "ENVIRONMENT CONFIGURATION" "⚙️"
printf "${YELLOW}${BOLD}🔧 Configuring environment${RESET}"
pulsing_dots 5 1
cp .env.example "$WEBROOT/.env"
status_ok "Environment template deployed"
draw_box "CONFIGURATION NOTICE" "IMPORTANT: Edit $WEBROOT/.env with your configuration" 60 "$YELLOW"
# ═══════════════════════════════════════════════════════════════════════════════
# 📝 PHASE 8: LOGGING INFRASTRUCTURE
# ═══════════════════════════════════════════════════════════════════════════════
section_header "8" "LOGGING INFRASTRUCTURE" "📝"
LOG_FILES=("access.log" "error.log" "ai-pipeline.log")
for i in "${!LOG_FILES[@]}"; do
progress_bar $((i+1)) ${#LOG_FILES[@]} 30 "Creating log files"
touch "$LOG_DIR/${LOG_FILES[$i]}"
sleep 0.2
done
echo
status_ok "Logging infrastructure established"
# ═══════════════════════════════════════════════════════════════════════════════
# 🔐 PHASE 9: PERMISSION MATRIX
# ═══════════════════════════════════════════════════════════════════════════════
section_header "9" "PERMISSION MATRIX CONFIGURATION" "🔐"
typewriter "Implementing security hardening..." 0.04 "$RED"
# Permission operations with progress
PERM_OPERATIONS=(
"chown -R www-data:www-data $WEBROOT"
"chmod -R 755 $WEBROOT"
"chmod 600 $WEBROOT/.env"
"chmod 755 $DATA_DIR $UPLOADS_DIR $LOG_DIR"
"chmod 644 $LOG_DIR/*.log"
)
for i in "${!PERM_OPERATIONS[@]}"; do
progress_bar $((i+1)) ${#PERM_OPERATIONS[@]} 45 "Setting permissions"
eval "${PERM_OPERATIONS[$i]}"
sleep 0.3
done
echo
if [ -f "$WEBROOT/server/entry.mjs" ]; then
chmod 755 "$WEBROOT/server/entry.mjs"
status_ok "Server entry point permissions configured"
fi
status_ok "Permission matrix locked down"
# ═══════════════════════════════════════════════════════════════════════════════
# ✅ PHASE 10: DEPLOYMENT VALIDATION
# ═══════════════════════════════════════════════════════════════════════════════
section_header "10" "DEPLOYMENT VALIDATION MATRIX" "✅"
VALIDATION_ERRORS=0
VALIDATIONS=(
"$WEBROOT/.env|Environment configuration"
"$WEBROOT/src/data/tools.yaml|Tools database"
)
# Check application files
if [ -f "$WEBROOT/index.html" ] || [ -d "$WEBROOT/server" ]; then
VALIDATIONS+=("$WEBROOT/index.html|Application files")
fi
echo
printf "${CYAN}${BOLD}🔍 Running comprehensive validation suite...${RESET}\n"
for validation in "${VALIDATIONS[@]}"; do
IFS='|' read -r file desc <<< "$validation"
printf "${YELLOW}Testing: $desc${RESET}"
pulsing_dots 3 1
if [ -f "$file" ] || [ -d "$file" ]; then
status_ok "$desc validated"
else
status_error "$desc missing"
((VALIDATION_ERRORS++))
fi
done
# ═══════════════════════════════════════════════════════════════════════════════
# 🎊 FINAL RESULTS SPECTACULAR
# ═══════════════════════════════════════════════════════════════════════════════
echo
if [ $VALIDATION_ERRORS -eq 0 ]; then
# Success celebration sequence
printf "${GREEN}${BOLD}${BG_GREEN}${WHITE}"
printf "%*s" $((COLS)) | tr ' ' '='
printf "${RESET}\n"
# Animated success banner
fancy_header "🎉 DEPLOYMENT SUCCESSFUL! 🎉" "All systems operational"
# Fireworks celebration
celebrate
# Next steps in a beautiful box
draw_box "🎯 MISSION BRIEFING - NEXT STEPS" "$(cat << EOF
1. 🔧 Configure environment variables in $WEBROOT/.env
• Set PUBLIC_BASE_URL, AI service endpoints
• Configure AUTH_SECRET and database connections
2. 🔄 Restart system services:
sudo systemctl restart forensic-pathways
sudo systemctl reload nginx
3. 🔍 Monitor system health:
sudo systemctl status forensic-pathways
sudo tail -f $LOG_DIR/error.log
🌐 Application fortress established at: $WEBROOT
🎯 Ready for production deployment!
EOF)" 70 "$GREEN"
# Final celebration
echo
printf "${BOLD}"
print_gradient_text "🚀 FORENSIC PATHWAYS DEPLOYMENT COMPLETE 🚀"
echo
else
# Error summary
draw_box "⚠️ DEPLOYMENT COMPLETED WITH WARNINGS" "Found $VALIDATION_ERRORS validation issues
Please review and resolve before proceeding" 60 "$YELLOW"
fi
# Final timestamp with style
echo
printf "${DIM}${ITALIC}Deployment completed at: "
printf "${BOLD}$(date '+%Y-%m-%d %H:%M:%S')${RESET}\n"
# Restore cursor
tput cnorm
# Final matrix effect fade-out
printf "${DIM}${GREEN}Deployment matrix shutting down...${RESET}\n"
matrix_rain 1
echo