- Add -9 (force kill) flag to all pkill commands - Kill Python backend processes explicitly - Kill npm and node processes - Use fuser to kill processes bound to ports 8000, 3001, 3002, 3003 - Add 1 second wait after cleanup - Ensures absolutely clean state before restart
191 lines
7.3 KiB
Bash
Executable File
191 lines
7.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# --- CONFIGURATION (Default values, will be overridden by network_configinventory.env) ---
|
|
BACKEND_PORT=8000
|
|
FRONTEND_PORT=3001
|
|
BACKEND_SSL_PORT=3002
|
|
FRONTEND_SSL_PORT=3003
|
|
SERVER_IP="localhost"
|
|
|
|
# Load Configuration from file if it exists
|
|
CONFIG_PATH="$(cd "$(dirname "$0")" && pwd)/inventory.env"
|
|
if [ -f "$CONFIG_PATH" ]; then
|
|
echo "⚙️ Loading network configuration from $CONFIG_PATH..."
|
|
# Export variables from inventory.env file (ignoring comments and empty lines)
|
|
export $(grep -v '^#' "$CONFIG_PATH" | xargs)
|
|
fi
|
|
|
|
echo "🚀 Starting TFM aInventory Stack with Dual Proxy..."
|
|
|
|
# 1. COMPREHENSIVE process cleanup - ensure absolute clean state
|
|
echo "Sweep: Comprehensive process cleanup..."
|
|
|
|
# Kill all known hanging processes
|
|
pkill -9 -f "uvicorn" 2>/dev/null || true
|
|
pkill -9 -f "next-server" 2>/dev/null || true
|
|
pkill -9 -f "local-ssl-proxy" 2>/dev/null || true
|
|
pkill -9 -f "python.*backend" 2>/dev/null || true
|
|
pkill -9 -f "python.*main:app" 2>/dev/null || true
|
|
pkill -9 -f "npm run dev" 2>/dev/null || true
|
|
pkill -9 -f "node.*next" 2>/dev/null || true
|
|
|
|
# Kill any remaining Python processes on port 8000 (backend)
|
|
fuser -k 8000/tcp 2>/dev/null || true
|
|
fuser -k 3001/tcp 2>/dev/null || true
|
|
fuser -k 3002/tcp 2>/dev/null || true
|
|
fuser -k 3003/tcp 2>/dev/null || true
|
|
|
|
# Extra wait to ensure processes are fully dead
|
|
sleep 1
|
|
|
|
echo "✅ Cleanup complete - all processes terminated"
|
|
|
|
# 2. Setup/Activate Virtual Environment
|
|
if [ ! -f ".venv/bin/activate" ]; then
|
|
echo "🌑 Creating virtual environment (.venv)..."
|
|
rm -rf .venv
|
|
apt install python3-venv
|
|
python3 -m venv .venv || { echo "❌ Failed to create venv"; exit 1; }
|
|
fi
|
|
source .venv/bin/activate || { echo "❌ Failed to activate venv"; exit 1; }
|
|
|
|
# 3. Check and Install Backend Dependencies
|
|
echo "📦 Updating Python dependencies..."
|
|
.venv/bin/pip install -r backend/requirements.txt
|
|
|
|
# 4. Get Local IP and set environment variables
|
|
LOCAL_IP=$(hostname -I | awk '{print $1}' || echo "localhost")
|
|
export ALLOWED_ORIGINS="http://localhost:$FRONTEND_PORT,http://localhost:$BACKEND_PORT,https://localhost:$FRONTEND_SSL_PORT,https://localhost:$BACKEND_SSL_PORT,https://$LOCAL_IP:$FRONTEND_SSL_PORT,https://$LOCAL_IP:$BACKEND_SSL_PORT"
|
|
|
|
# 4.0 Include EXTRA_ALLOWED_ORIGINS from inventory.env (VPN, Tailscale, etc.)
|
|
if [ ! -z "$EXTRA_ALLOWED_ORIGINS" ]; then
|
|
echo "🔌 Adding extra CORS origins from inventory.env..."
|
|
IFS=',' read -ra EXTRA_ADDRS <<< "$EXTRA_ALLOWED_ORIGINS"
|
|
for addr in "${EXTRA_ADDRS[@]}"; do
|
|
TRIMMED=$(echo "$addr" | xargs)
|
|
# Add both HTTP (for localhost dev) and HTTPS (for production)
|
|
export ALLOWED_ORIGINS="$ALLOWED_ORIGINS,http://$TRIMMED:$FRONTEND_PORT,http://$TRIMMED:$BACKEND_PORT,https://$TRIMMED:$FRONTEND_SSL_PORT,https://$TRIMMED:$BACKEND_SSL_PORT"
|
|
done
|
|
fi
|
|
|
|
export JWT_SECRET_KEY="${JWT_SECRET_KEY:-ephemeral-dev-key-$(date +%s)}"
|
|
export DATA_DIR="$(cd "$(dirname "$0")" && pwd)/data"
|
|
export LOGS_DIR="$(cd "$(dirname "$0")" && pwd)/logs"
|
|
|
|
# First-run: initialize data directories and config templates
|
|
echo "🔧 Initializing runtime data directories..."
|
|
bash "$(cd "$(dirname "$0")" && pwd)/scripts/init_data.sh"
|
|
|
|
# 4.1 Sync Network Config to Frontend for runtime discovery
|
|
echo "🔌 Syncing network configuration to frontend..."
|
|
cat <<EOF > frontend/public/network.json
|
|
{
|
|
"SERVER_IP": "$SERVER_IP",
|
|
"BACKEND_PORT": $BACKEND_PORT,
|
|
"BACKEND_SSL_PORT": $BACKEND_SSL_PORT,
|
|
"FRONTEND_PORT": $FRONTEND_PORT,
|
|
"FRONTEND_SSL_PORT": $FRONTEND_SSL_PORT
|
|
}
|
|
EOF
|
|
|
|
echo "🔥 Starting Backend on port $BACKEND_PORT..."
|
|
echo " CORS origins: $ALLOWED_ORIGINS"
|
|
.venv/bin/python -m uvicorn backend.main:app --host 0.0.0.0 --port $BACKEND_PORT --reload &
|
|
|
|
# 5. Prepare Frontend Dev Origins from EXTRA_ALLOWED_ORIGINS
|
|
# Convert subnet notation (10.0.0.0/24) to wildcard patterns (10.0.0.*)
|
|
ALLOWED_DEV_ORIGINS="localhost,127.0.0.1,*.local"
|
|
if [ ! -z "$EXTRA_ALLOWED_ORIGINS" ]; then
|
|
IFS=',' read -ra EXTRA_ADDRS <<< "$EXTRA_ALLOWED_ORIGINS"
|
|
for addr in "${EXTRA_ADDRS[@]}"; do
|
|
TRIMMED=$(echo "$addr" | xargs)
|
|
if [[ "$TRIMMED" == *"/"* ]]; then
|
|
# Subnet notation: convert 100.78.182.0/24 -> 100.78.182.*
|
|
SUBNET_PREFIX=$(echo "$TRIMMED" | cut -d'/' -f1)
|
|
SUBNET_PATTERN="${SUBNET_PREFIX%.*}.*"
|
|
ALLOWED_DEV_ORIGINS="$ALLOWED_DEV_ORIGINS,$SUBNET_PATTERN"
|
|
else
|
|
# Individual IP: add wildcard for nearby IPs (e.g., 192.168.1.100 -> 192.168.1.*)
|
|
IP_PATTERN="${TRIMMED%.*}.*"
|
|
ALLOWED_DEV_ORIGINS="$ALLOWED_DEV_ORIGINS,$IP_PATTERN"
|
|
fi
|
|
done
|
|
fi
|
|
export ALLOWED_DEV_ORIGINS
|
|
|
|
# 5. Start Frontend (Next.js)
|
|
echo "💻 Starting Frontend on port $FRONTEND_PORT..."
|
|
echo " Dev origins: $ALLOWED_DEV_ORIGINS"
|
|
|
|
# Check Node.js version
|
|
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
|
|
if [ "$NODE_VERSION" -lt 20 ]; then
|
|
echo "⚠️ WARNING: Node.js v20+ required, but found $(node -v)"
|
|
echo " Please upgrade Node.js: https://nodejs.org/"
|
|
fi
|
|
|
|
cd frontend
|
|
echo "📦 Installing frontend dependencies..."
|
|
npm install
|
|
ALLOWED_DEV_ORIGINS="$ALLOWED_DEV_ORIGINS" npm run dev -- -p $FRONTEND_PORT &
|
|
cd ..
|
|
|
|
# 6. Start Proxies (Crucial for Mobile/Tablet Camera & Sync)
|
|
# Bind to SERVER_IP (not 0.0.0.0) so VPN/remote clients can reach the server
|
|
PROXY_HOSTNAME=${SERVER_IP:-0.0.0.0}
|
|
echo "🔐 Starting SSL proxies on $PROXY_HOSTNAME..."
|
|
npx local-ssl-proxy --source $BACKEND_SSL_PORT --target $BACKEND_PORT --hostname $PROXY_HOSTNAME > /dev/null 2>&1 &
|
|
npx local-ssl-proxy --source $FRONTEND_SSL_PORT --target $FRONTEND_PORT --hostname $PROXY_HOSTNAME > /dev/null 2>&1 &
|
|
|
|
# 7. Signal handlers for clean shutdown
|
|
cleanup() {
|
|
echo ""
|
|
echo "🛑 Shutting down services..."
|
|
pkill -P $$ > /dev/null 2>&1
|
|
kill $(jobs -p) 2>/dev/null || true
|
|
pkill -f "uvicorn" 2>/dev/null || true
|
|
pkill -f "next-server" 2>/dev/null || true
|
|
pkill -f "local-ssl-proxy" 2>/dev/null || true
|
|
echo "✅ Cleanup complete"
|
|
exit 0
|
|
}
|
|
|
|
# Trap Ctrl-C (SIGINT) and other termination signals
|
|
trap cleanup SIGINT SIGTERM EXIT
|
|
|
|
# 8. Print Unified Access Banner
|
|
|
|
# Colors
|
|
GREEN='\033[0;32m'
|
|
BOLD='\033[1m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
echo ""
|
|
echo -e "${GREEN}=======================================================${NC}"
|
|
echo -e "${GREEN}${BOLD} 🚀 TFM aInventory UNIFIED ACCESS${NC}"
|
|
echo -e "${GREEN}=======================================================${NC}"
|
|
echo ""
|
|
echo -e " USE THIS URL ON BOTH DESKTOP & MOBILE:"
|
|
echo -e " 👉 ${GREEN}${BOLD}https://$LOCAL_IP:$FRONTEND_SSL_PORT${NC}"
|
|
echo -e " (Or ${GREEN}https://localhost:$FRONTEND_SSL_PORT${NC} on this Mac)"
|
|
|
|
if [ ! -z "$EXTRA_ALLOWED_ORIGINS" ]; then
|
|
echo -e " EXTERNAL/VPN ACCESS points:"
|
|
IFS=',' read -ra ADDR <<< "$EXTRA_ALLOWED_ORIGINS"
|
|
for exp in "${ADDR[@]}"; do
|
|
# Trim spaces and print
|
|
TRIMMED=$(echo $exp | xargs)
|
|
echo -e " 👉 ${GREEN}${BOLD}https://$TRIMMED:$FRONTEND_SSL_PORT${NC}"
|
|
done
|
|
fi
|
|
echo ""
|
|
echo -e " ${YELLOW}${BOLD}NOTE:${NC} If you see a 'Not Private' warning,"
|
|
echo -e " Click 'Advanced' -> 'Proceed' to continue."
|
|
echo -e "${GREEN}=======================================================${NC}"
|
|
echo "Keep this window open while working. Press Ctrl-C to stop."
|
|
echo -e "${GREEN}=======================================================${NC}"
|
|
|
|
# Wait for background processes
|
|
wait
|