424 lines
13 KiB
Bash
424 lines
13 KiB
Bash
|
|
#!/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 ""
|