#!/bin/bash # Complete fix for explorer.d-bis.org # This script fixes the explorer by deploying the static frontend and ensuring nginx is properly configured # Can be run from Proxmox host or inside VMID 5000 set -euo pipefail VMID=5000 VM_IP="192.168.11.140" FRONTEND_SOURCE="/home/intlc/projects/proxmox/explorer-monorepo/frontend/public/index.html" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Detect if running inside container or from Proxmox host if [ -f "/proc/1/cgroup" ] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then EXEC_PREFIX="" IS_CONTAINER=true echo "Detected: Running inside LXC container" else EXEC_PREFIX="pct exec $VMID --" IS_CONTAINER=false echo "Detected: Running from Proxmox host" # Check if VMID 5000 exists if ! pct list | grep -q "^$VMID "; then echo "❌ VMID $VMID not found!" echo "Attempting to deploy static server locally..." IS_CONTAINER=false NO_VMID=true else NO_VMID=false fi fi echo "==========================================" echo "Complete Explorer Fix" echo "==========================================" echo "Frontend Source: $FRONTEND_SOURCE" echo "==========================================" echo "" # Step 1: Verify frontend file exists echo "=== Step 1: Verifying frontend file ===" if [ ! -f "$FRONTEND_SOURCE" ]; then echo "❌ Frontend file not found: $FRONTEND_SOURCE" echo "Attempting to find frontend file..." # Try alternate locations ALTERNATE_LOCATIONS=( "$REPO_ROOT/explorer-monorepo/frontend/public/index.html" "$HOME/projects/proxmox/explorer-monorepo/frontend/public/index.html" "./frontend/public/index.html" "../frontend/public/index.html" ) FOUND=false for loc in "${ALTERNATE_LOCATIONS[@]}"; do if [ -f "$loc" ]; then FRONTEND_SOURCE="$loc" echo "✅ Found frontend at: $FRONTEND_SOURCE" FOUND=true break fi done if [ "$FOUND" = false ]; then echo "❌ Could not find frontend file!" exit 1 fi else echo "✅ Frontend file found: $FRONTEND_SOURCE" fi echo "" # Function to deploy to VMID 5000 deploy_to_vmid() { echo "=== Deploying to VMID $VMID ===" # Create directory $EXEC_PREFIX mkdir -p /var/www/html $EXEC_PREFIX chown -R www-data:www-data /var/www/html 2>/dev/null || true # Backup existing $EXEC_PREFIX bash << 'BACKUP' if [ -f /var/www/html/index.html ]; then cp /var/www/html/index.html /var/www/html/index.html.backup.$(date +%Y%m%d_%H%M%S) 2>/dev/null || true fi BACKUP # Deploy frontend if [ "$IS_CONTAINER" = true ]; then cp "$FRONTEND_SOURCE" /var/www/html/index.html chown www-data:www-data /var/www/html/index.html else pct push $VMID "$FRONTEND_SOURCE" /var/www/html/index.html $EXEC_PREFIX chown www-data:www-data /var/www/html/index.html 2>/dev/null || true fi echo "✅ Frontend deployed to /var/www/html/index.html" # Update nginx configuration update_nginx_config } # Function to update nginx configuration update_nginx_config() { echo "" echo "=== Updating nginx configuration ===" # Check if nginx config exists NGINX_CONFIG="/etc/nginx/sites-available/blockscout" if ! $EXEC_PREFIX test -f "$NGINX_CONFIG" 2>/dev/null; then echo "⚠️ Nginx config not found at $NGINX_CONFIG, creating new config..." create_nginx_config return fi # Backup config $EXEC_PREFIX cp "$NGINX_CONFIG" "${NGINX_CONFIG}.backup.$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true # Update config to serve static frontend $EXEC_PREFIX bash << 'NGINX_UPDATE' CONFIG_FILE="/etc/nginx/sites-available/blockscout" # Check if root location already serves static files if ! grep -q "root /var/www/html" "$CONFIG_FILE"; then # Update HTTPS server block sed -i '/listen 443/,/^}/ { /location = \/ {/,/^ }/ { s|try_files.*|try_files /index.html =404;| } /location \/ {/ { /proxy_pass/,/^ }/ { s|proxy_pass.*|root /var/www/html;| s|proxy_http_version.*|| s|proxy_set_header.*|| s|proxy_read_timeout.*|| /proxy_/d } } }' "$CONFIG_FILE" # Ensure root location serves static files if ! grep -q "location = / {" "$CONFIG_FILE"; then # Add location block after server_name sed -i '/server_name/a\ # Serve custom frontend for root path\ location = / {\ root /var/www/html;\ try_files /index.html =404;\ }' "$CONFIG_FILE" fi echo "✅ Nginx config updated" else echo "✅ Nginx already configured to serve static files" fi # Test and reload nginx if nginx -t 2>/dev/null; then systemctl reload nginx 2>/dev/null || systemctl restart nginx 2>/dev/null || true echo "✅ Nginx reloaded" else echo "⚠️ Nginx config test failed, skipping reload" nginx -t 2>&1 || true fi NGINX_UPDATE } # Function to create new nginx config create_nginx_config() { $EXEC_PREFIX bash << 'CREATE_NGINX' cat > /etc/nginx/sites-available/blockscout << 'NGINX_EOF' # HTTP server - redirect to HTTPS server { listen 80; listen [::]:80; server_name explorer.d-bis.org 192.168.11.140; location /.well-known/acme-challenge/ { root /var/www/html; } # API endpoint - proxy to Blockscout if available location /api/ { proxy_pass http://127.0.0.1:4000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; add_header Access-Control-Allow-Origin *; } # Serve static frontend location = / { root /var/www/html; try_files /index.html =404; } # All other requests redirect to HTTPS location / { return 301 https://$host$request_uri; } } # HTTPS server server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name explorer.d-bis.org 192.168.11.140; # SSL configuration (optional - Cloudflare may handle SSL) # ssl_certificate /etc/letsencrypt/live/explorer.d-bis.org/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/explorer.d-bis.org/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # Security headers add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; access_log /var/log/nginx/blockscout-access.log; error_log /var/log/nginx/blockscout-error.log; # Serve custom frontend for root path location = / { root /var/www/html; try_files /index.html =404; } # Serve static assets location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { root /var/www/html; expires 1y; add_header Cache-Control "public, immutable"; } # API endpoint - proxy to Blockscout if available location /api/ { proxy_pass http://127.0.0.1:4000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300s; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type"; } } NGINX_EOF # Enable site ln -sf /etc/nginx/sites-available/blockscout /etc/nginx/sites-enabled/blockscout 2>/dev/null || true # Test and reload if nginx -t 2>/dev/null; then systemctl reload nginx 2>/dev/null || systemctl restart nginx 2>/dev/null || true echo "✅ Nginx config created and reloaded" else echo "⚠️ Nginx config test failed" nginx -t 2>&1 || true fi CREATE_NGINX } # Function to start/check nginx ensure_nginx_running() { echo "" echo "=== Ensuring nginx is running ===" if $EXEC_PREFIX systemctl is-active nginx >/dev/null 2>&1; then echo "✅ Nginx is running" else echo "⚠️ Nginx is not running, starting..." $EXEC_PREFIX systemctl start nginx 2>/dev/null || true sleep 2 if $EXEC_PREFIX systemctl is-active nginx >/dev/null 2>&1; then echo "✅ Nginx started" else echo "❌ Failed to start nginx" echo "Check logs: $EXEC_PREFIX journalctl -u nginx -n 20" fi fi } # Function for local server (fallback) - must be defined before use create_local_server() { echo "Creating local server option..." cat > "$REPO_ROOT/explorer-monorepo/scripts/serve-explorer-local.sh" << 'LOCAL_SERVER' #!/bin/bash # Simple local server for explorer (fallback option) # Usage: ./serve-explorer-local.sh [port] PORT=${1:-8080} FRONTEND_DIR="$(cd "$(dirname "$0")/../frontend/public" && pwd)" if [ ! -f "$FRONTEND_DIR/index.html" ]; then echo "❌ Frontend not found at: $FRONTEND_DIR/index.html" exit 1 fi echo "Serving explorer on http://localhost:$PORT" echo "Frontend: $FRONTEND_DIR" cd "$FRONTEND_DIR" # Try Python 3 first, then Python 2 if command -v python3 >/dev/null 2>&1; then python3 -m http.server "$PORT" elif command -v python >/dev/null 2>&1; then python -m SimpleHTTPServer "$PORT" else echo "❌ Python not found. Install Python to use this script." exit 1 fi LOCAL_SERVER chmod +x "$REPO_ROOT/explorer-monorepo/scripts/serve-explorer-local.sh" echo "✅ Local server script created: $REPO_ROOT/explorer-monorepo/scripts/serve-explorer-local.sh" } # Main deployment if [ "${NO_VMID:-false}" != "true" ] && [ "$IS_CONTAINER" = false ]; then # Deploy to VMID 5000 deploy_to_vmid ensure_nginx_running else # Local deployment or container if [ "$IS_CONTAINER" = true ]; then # Running inside container echo "=== Deploying inside container ===" mkdir -p /var/www/html cp "$FRONTEND_SOURCE" /var/www/html/index.html chown www-data:www-data /var/www/html/index.html 2>/dev/null || true update_nginx_config ensure_nginx_running else # Local fallback - create simple HTTP server script echo "⚠️ VMID 5000 not accessible, creating local deployment option" create_local_server fi fi # Function for local server (fallback) - must be defined before use create_local_server() { echo "Creating local server option..." cat > "$REPO_ROOT/explorer-monorepo/scripts/serve-explorer-local.sh" << 'LOCAL_SERVER' #!/bin/bash # Simple local server for explorer (fallback option) # Usage: ./serve-explorer-local.sh [port] PORT=${1:-8080} FRONTEND_DIR="$(cd "$(dirname "$0")/../frontend/public" && pwd)" if [ ! -f "$FRONTEND_DIR/index.html" ]; then echo "❌ Frontend not found at: $FRONTEND_DIR/index.html" exit 1 fi echo "Serving explorer on http://localhost:$PORT" echo "Frontend: $FRONTEND_DIR" cd "$FRONTEND_DIR" # Try Python 3 first, then Python 2 if command -v python3 >/dev/null 2>&1; then python3 -m http.server "$PORT" elif command -v python >/dev/null 2>&1; then python -m SimpleHTTPServer "$PORT" else echo "❌ Python not found. Install Python to use this script." exit 1 fi LOCAL_SERVER chmod +x "$REPO_ROOT/explorer-monorepo/scripts/serve-explorer-local.sh" echo "✅ Local server script created: $REPO_ROOT/explorer-monorepo/scripts/serve-explorer-local.sh" } # Final verification echo "" echo "=== Verification ===" if [ "${NO_VMID:-false}" != "true" ] && [ "$IS_CONTAINER" = false ]; then # Check if file exists if $EXEC_PREFIX test -f /var/www/html/index.html; then echo "✅ Frontend file deployed: /var/www/html/index.html" else echo "❌ Frontend file not found" fi # Test HTTP endpoint HTTP_TEST=$($EXEC_PREFIX curl -s -o /dev/null -w '%{http_code}' --connect-timeout 3 http://localhost/ 2>/dev/null || echo "000") if [ "$HTTP_TEST" = "200" ]; then echo "✅ HTTP endpoint responding (200)" else echo "⚠️ HTTP endpoint returned: $HTTP_TEST" fi elif [ "$IS_CONTAINER" = true ]; then if [ -f /var/www/html/index.html ]; then echo "✅ Frontend file deployed: /var/www/html/index.html" HTTP_TEST=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 3 http://localhost/ 2>/dev/null || echo "000") if [ "$HTTP_TEST" = "200" ]; then echo "✅ HTTP endpoint responding (200)" else echo "⚠️ HTTP endpoint returned: $HTTP_TEST" fi fi fi echo "" echo "==========================================" echo "Fix Complete" echo "==========================================" echo "" echo "Next steps:" echo "1. Verify explorer is accessible: curl -I https://explorer.d-bis.org" echo "2. Check nginx logs if issues persist: tail -f /var/log/nginx/blockscout-error.log" echo "3. Ensure Cloudflare tunnel is running if using Cloudflare" echo ""