#!/bin/bash # Restart Ginxsom Development Environment # Combines nginx and FastCGI restart operations for debugging # WARNING: This script DELETES all databases in db/ for fresh testing # Configuration # Parse command line arguments TEST_MODE=1 # Default to test mode FOLLOW_LOGS=0 while [[ $# -gt 0 ]]; do case $1 in -t|--test-keys) TEST_MODE=1 shift ;; -p|--production) TEST_MODE=0 shift ;; --follow) FOLLOW_LOGS=1 shift ;; *) echo "Unknown option: $1" echo "Usage: $0 [-t|--test-keys] [-p|--production] [--follow]" echo " -t, --test-keys Use test mode with keys from .test_keys (DEFAULT)" echo " -p, --production Use production mode (generate new keys)" echo " --follow Follow logs in real-time" exit 1 ;; esac done # Check for --follow flag if [[ $FOLLOW_LOGS -eq 1 ]]; then echo "=== Following logs in real-time ===" echo "Monitoring: nginx error, nginx access, app stderr, app stdout" echo "Press Ctrl+C to stop following logs" echo # Start tailing multiple log files mkdir -p logs/nginx logs/app touch logs/nginx/error.log logs/nginx/access.log logs/app/stderr.log logs/app/stdout.log tail -f logs/nginx/error.log logs/nginx/access.log logs/app/stderr.log logs/app/stdout.log & wait exit 0 fi # Detect architecture for static binary name ARCH=$(uname -m) case "$ARCH" in x86_64) STATIC_BINARY="./build/ginxsom-fcgi_static_x86_64" ;; aarch64|arm64) STATIC_BINARY="./build/ginxsom-fcgi_static_arm64" ;; *) STATIC_BINARY="./build/ginxsom-fcgi_static_${ARCH}" ;; esac # Use static binary if available, fallback to dynamic if [ -f "$STATIC_BINARY" ]; then FCGI_BINARY="$STATIC_BINARY" echo "Using static binary: $FCGI_BINARY" else FCGI_BINARY="./build/ginxsom-fcgi" echo "Static binary not found, using dynamic binary: $FCGI_BINARY" fi SOCKET_PATH="/tmp/ginxsom-fcgi.sock" PID_FILE="/tmp/ginxsom-fcgi.pid" NGINX_CONFIG="config/local-nginx.conf" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Ensure log directories exist with proper permissions echo "Creating log directories..." mkdir -p logs/nginx logs/app touch logs/app/stderr.log logs/app/stdout.log logs/nginx/error.log logs/nginx/access.log chmod 644 logs/app/stderr.log logs/app/stdout.log logs/nginx/error.log logs/nginx/access.log chmod 755 logs/nginx logs/app if [ $TEST_MODE -eq 1 ]; then echo -e "${YELLOW}=== Ginxsom Development Environment Restart (TEST MODE) ===${NC}" echo "Using test keys from .test_keys file" else echo -e "${YELLOW}=== Ginxsom Development Environment Restart ===${NC}" fi echo "Starting full restart sequence..." # Function to check if a process is running check_process() { local pid=$1 kill -0 "$pid" 2>/dev/null } # Function to wait for process to stop wait_for_stop() { local pid=$1 local timeout=${2:-10} local count=0 while check_process "$pid" && [ $count -lt $timeout ]; do sleep 1 ((count++)) done if check_process "$pid"; then echo -e "${RED}Warning: Process $pid still running after ${timeout}s${NC}" return 1 fi return 0 } # Step 1: Stop nginx echo -e "\n${YELLOW}1. Stopping nginx...${NC}" # First try to stop nginx gracefully using our config if pgrep -f "nginx.*${NGINX_CONFIG}" > /dev/null; then echo "Found nginx processes with our config, stopping gracefully..." nginx -p . -c "${NGINX_CONFIG}" -s stop 2>/dev/null sleep 2 fi # Kill any remaining nginx processes (including those on port 9001) NGINX_PIDS=$(pgrep nginx) if [ ! -z "$NGINX_PIDS" ]; then echo "Found running nginx processes, stopping..." echo "Nginx PIDs: $NGINX_PIDS" # Try graceful stop first sudo nginx -s stop 2>/dev/null || true sleep 2 # Force kill any remaining nginx processes NGINX_PIDS=$(pgrep nginx) if [ ! -z "$NGINX_PIDS" ]; then echo "Force killing remaining nginx processes: $NGINX_PIDS" sudo kill -9 $NGINX_PIDS 2>/dev/null || true fi echo -e "${GREEN}nginx stopped${NC}" else echo "nginx not running" fi # Step 2: Stop FastCGI echo -e "\n${YELLOW}2. Stopping FastCGI application...${NC}" # Method 1: Stop via PID file if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") echo "Found PID file with process $PID" if check_process "$PID"; then echo "Stopping FastCGI process $PID" kill "$PID" if wait_for_stop "$PID" 5; then echo -e "${GREEN}FastCGI process stopped gracefully${NC}" else echo "Force killing FastCGI process $PID" kill -9 "$PID" 2>/dev/null fi else echo "PID $PID not running, cleaning up PID file" fi rm -f "$PID_FILE" fi # Method 2: Kill any remaining ginxsom-fcgi processes FCGI_PIDS=$(pgrep -f "ginxsom-fcgi") if [ ! -z "$FCGI_PIDS" ]; then echo "Found additional FastCGI processes: $FCGI_PIDS" kill $FCGI_PIDS 2>/dev/null sleep 2 # Force kill if still running FCGI_PIDS=$(pgrep -f "ginxsom-fcgi") if [ ! -z "$FCGI_PIDS" ]; then echo "Force killing FastCGI processes: $FCGI_PIDS" kill -9 $FCGI_PIDS 2>/dev/null fi fi # Method 3: Clean up socket if [ -S "$SOCKET_PATH" ]; then echo "Removing old socket: $SOCKET_PATH" rm -f "$SOCKET_PATH" fi echo -e "${GREEN}FastCGI cleanup complete${NC}" # Step 3: Always rebuild FastCGI binary with static build echo -e "\n${YELLOW}3. Rebuilding FastCGI binary (static build)...${NC}" echo "Cleaning old build artifacts to ensure fresh embedding..." make clean echo "Removing local embedded header to prevent Docker cache issues..." rm -f src/admin_interface_embedded.h echo "Building static binary with Docker..." make static if [ $? -ne 0 ]; then echo -e "${RED}Static build failed! Cannot continue.${NC}" echo -e "${RED}Docker must be available and running for static builds.${NC}" exit 1 fi # Update FCGI_BINARY to use the newly built static binary ARCH=$(uname -m) case "$ARCH" in x86_64) FCGI_BINARY="./build/ginxsom-fcgi_static_x86_64" ;; aarch64|arm64) FCGI_BINARY="./build/ginxsom-fcgi_static_arm64" ;; *) FCGI_BINARY="./build/ginxsom-fcgi_static_${ARCH}" ;; esac echo -e "${GREEN}Static build complete: $FCGI_BINARY${NC}" # Step 3.5: Clean database directory for fresh testing echo -e "\n${YELLOW}3.5. Cleaning database directory...${NC}" echo "Removing all existing databases for fresh start..." # Remove all .db files in db/ directory if ls db/*.db 1> /dev/null 2>&1; then echo "Found databases to remove:" ls -lh db/*.db rm -f db/*.db echo -e "${GREEN}Database cleanup complete${NC}" else echo "No existing databases found" fi # Step 3.75: Handle keys based on mode echo -e "\n${YELLOW}3.75. Configuring server keys...${NC}" if [ $TEST_MODE -eq 1 ]; then # Test mode: verify .test_keys file exists if [ ! -f ".test_keys" ]; then echo -e "${RED}ERROR: .test_keys file not found${NC}" echo -e "${RED}Test mode requires .test_keys file in project root${NC}" exit 1 fi # Extract test server pubkey to determine database name TEST_PUBKEY=$(grep "^SERVER_PUBKEY=" .test_keys | cut -d"'" -f2) if [ -z "$TEST_PUBKEY" ]; then echo -e "${RED}ERROR: Could not extract SERVER_PUBKEY from .test_keys${NC}" exit 1 fi echo -e "${GREEN}Test mode: Will use keys from .test_keys${NC}" echo -e "${GREEN}Fresh test database will be created as: db/${TEST_PUBKEY}.db${NC}" else # Production mode: databases were cleaned, will generate new keypair echo -e "${YELLOW}Production mode: Fresh start with new keypair${NC}" echo -e "${YELLOW}New database will be created as db/.db${NC}" fi # Step 4: Start FastCGI echo -e "\n${YELLOW}4. Starting FastCGI application...${NC}" echo "Socket: $SOCKET_PATH" echo "Binary: $FCGI_BINARY" # Check if spawn-fcgi is available if ! command -v spawn-fcgi &> /dev/null; then echo -e "${RED}Error: spawn-fcgi not found. Please install it:${NC}" echo " Ubuntu/Debian: sudo apt-get install spawn-fcgi" echo " macOS: brew install spawn-fcgi" exit 1 fi # Start FastCGI application with proper logging (daemonized but with redirected streams) # Set debug environment variable for pubkey extraction diagnostics echo "Setting GINX_DEBUG environment for pubkey extraction diagnostics" export GINX_DEBUG=1 # Build command line arguments based on mode FCGI_ARGS="--storage-dir blobs" if [ $TEST_MODE -eq 1 ]; then FCGI_ARGS="$FCGI_ARGS --test-keys" echo -e "${YELLOW}Starting FastCGI in TEST MODE with test keys${NC}" else # Production mode: databases were cleaned, will generate new keys echo -e "${YELLOW}Starting FastCGI in production mode - will generate new keys and create database${NC}" fi # Start FastCGI application with proper logging echo "FastCGI starting at $(date)" >> logs/app/stderr.log # Use nohup with spawn-fcgi -n to keep process running with redirected output # The key is: nohup prevents HUP signal, -n prevents daemonization (keeps stderr connected) nohup spawn-fcgi -n -s "$SOCKET_PATH" -M 666 -u "$USER" -g "$USER" -- "$FCGI_BINARY" $FCGI_ARGS >>logs/app/stdout.log 2>>logs/app/stderr.log "$PID_FILE" # Give it a moment to start sleep 1 if check_process "$FCGI_PID"; then echo -e "${GREEN}FastCGI application started successfully${NC}" echo "PID: $FCGI_PID" echo -e "${GREEN}Process confirmed running${NC}" else echo -e "${RED}Failed to start FastCGI application${NC}" echo -e "${RED}Process may have crashed immediately${NC}" exit 1 fi # Step 5: Start nginx echo -e "\n${YELLOW}5. Starting nginx...${NC}" if [ ! -f "$NGINX_CONFIG" ]; then echo -e "${RED}Error: nginx config not found at $NGINX_CONFIG${NC}" exit 1 fi # Test nginx configuration first nginx -p . -c "$NGINX_CONFIG" -t if [ $? -ne 0 ]; then echo -e "${RED}nginx configuration test failed!${NC}" exit 1 fi # Start nginx nginx -p . -c "$NGINX_CONFIG" if [ $? -eq 0 ]; then echo -e "${GREEN}nginx started successfully${NC}" # Verify nginx is running sleep 1 if pgrep -f "nginx.*${NGINX_CONFIG}" > /dev/null; then echo -e "${GREEN}nginx confirmed running${NC}" else echo -e "${RED}Warning: nginx may have crashed${NC}" exit 1 fi else echo -e "${RED}Failed to start nginx${NC}" exit 1 fi # Step 6: Final status check echo -e "\n${YELLOW}6. Final status check...${NC}" # Check FastCGI if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") if check_process "$PID"; then echo -e "${GREEN}✓ FastCGI running (PID: $PID)${NC}" else echo -e "${RED}✗ FastCGI not running${NC}" fi else echo -e "${RED}✗ FastCGI PID file missing${NC}" fi # Check nginx if pgrep -f "nginx.*${NGINX_CONFIG}" > /dev/null; then NGINX_PIDS=$(pgrep -f "nginx.*${NGINX_CONFIG}" | tr '\n' ' ') echo -e "${GREEN}✓ nginx running (PIDs: $NGINX_PIDS)${NC}" else echo -e "${RED}✗ nginx not running${NC}" fi # Check socket if [ -S "$SOCKET_PATH" ]; then echo -e "${GREEN}✓ FastCGI socket exists: $SOCKET_PATH${NC}" else echo -e "${RED}✗ FastCGI socket missing: $SOCKET_PATH${NC}" fi echo -e "\n${GREEN}=== Restart sequence complete ===${NC}" echo -e "${YELLOW}To stop all processes, run: nginx -p . -c $NGINX_CONFIG -s stop && kill \$(cat $PID_FILE 2>/dev/null)${NC}" echo -e "${YELLOW}To monitor logs, check: logs/nginx/error.log, logs/nginx/access.log, logs/app/stderr.log, logs/app/stdout.log${NC}" echo -e "\n${YELLOW}Server is available at:${NC}" echo -e " ${GREEN}HTTP:${NC} http://localhost:9001" echo -e " ${GREEN}HTTPS:${NC} https://localhost:9443" echo -e "\n${YELLOW}Admin WebSocket endpoint:${NC}" echo -e " ${GREEN}WSS:${NC} wss://localhost:9443/admin (via nginx proxy)" echo -e " ${GREEN}WS:${NC} ws://localhost:9001/admin (via nginx proxy)" echo -e " ${GREEN}Direct:${NC} ws://localhost:9442 (direct connection)"