#!/usr/bin/env bash # Complete all steps to provide explorer API access: # 1) Start Blockscout in VMID 5000 # 2) Deploy frontend and nginx config (location /api/ -> port 4000) # 3) Wait for API to respond # 4) Run verification # # Run from the Proxmox host that has VMID 5000, or from your machine with: # EXPLORER_VM_HOST=root@192.168.11.12 bash scripts/complete-explorer-api-access.sh # (uses PROXMOX_R630_02 from repo .env if set and EXPLORER_VM_HOST is not) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" [ -f "$REPO_ROOT/../.env" ] && source "$REPO_ROOT/../.env" 2>/dev/null || true [ -f "$REPO_ROOT/.env" ] && source "$REPO_ROOT/.env" 2>/dev/null || true VMID="${EXPLORER_VMID:-5000}" EXPLORER_NODE="${EXPLORER_VM_HOST:-${PROXMOX_R630_02:-192.168.11.12}}" # If EXPLORER_VM_HOST is user@host, use it; else we have only IP if [[ "$EXPLORER_NODE" == *"@"* ]]; then SSH_TARGET="$EXPLORER_NODE" else SSH_TARGET="root@$EXPLORER_NODE" fi # --- Remote mode: no pct here, run on Proxmox node via SSH --- if ! command -v pct &>/dev/null || ! pct list 2>/dev/null | grep -q "^$VMID "; then if [ -n "${EXPLORER_VM_HOST:-}" ] || [ -n "${PROXMOX_R630_02:-}" ]; then echo "==============================================" echo "Running on Proxmox node via SSH: $SSH_TARGET" echo "==============================================" FRONTEND_FILE="$REPO_ROOT/frontend/public/index.html" if [ ! -f "$FRONTEND_FILE" ]; then echo "❌ Frontend not found: $FRONTEND_FILE" exit 1 fi scp -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$FRONTEND_FILE" "$SSH_TARGET:/tmp/explorer-index.html" || exit 1 scp -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$SCRIPT_DIR/complete-explorer-api-access.sh" "$SSH_TARGET:/tmp/complete-explorer-api-access.sh" || true scp -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$SCRIPT_DIR/verify-explorer-api-access.sh" "$SSH_TARGET:/tmp/verify-explorer-api-access.sh" 2>/dev/null || true ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$SSH_TARGET" "FRONTEND_SOURCE=/tmp/explorer-index.html EXPLORER_VM_HOST= bash /tmp/complete-explorer-api-access.sh" exit $? else echo "❌ pct not found and EXPLORER_VM_HOST / PROXMOX_R630_02 not set." echo " Run this script on the Proxmox host that has VMID $VMID, or set:" echo " EXPLORER_VM_HOST=root@" exit 1 fi fi # --- Local mode: we have pct and VMID 5000 --- EXEC_PREFIX="pct exec $VMID --" FRONTEND_SOURCE="${FRONTEND_SOURCE:-$REPO_ROOT/frontend/public/index.html}" echo "==============================================" echo "Complete Explorer API Access (VMID $VMID)" echo "==============================================" echo "" # Step 1: Start Blockscout echo "=== Step 1: Starting Blockscout ===" $EXEC_PREFIX bash -c ' set -e BLOCKSCOUT_DIR="/opt/blockscout" if [ -f "$BLOCKSCOUT_DIR/docker-compose.yml" ]; then cd "$BLOCKSCOUT_DIR" docker compose up -d blockscout 2>/dev/null || docker compose up -d 2>/dev/null || true else CONTAINER=$(docker ps -a --format "{{.Names}}" 2>/dev/null | grep -E "blockscout" | grep -v postgres | head -1) if [ -n "$CONTAINER" ]; then docker start $CONTAINER 2>/dev/null || true fi fi ' 2>/dev/null || true echo "✅ Blockscout start requested" sleep 3 echo "" # Step 2: Deploy frontend echo "=== Step 2: Deploying frontend ===" if [ ! -f "$FRONTEND_SOURCE" ]; then echo "❌ Frontend not found: $FRONTEND_SOURCE" exit 1 fi $EXEC_PREFIX mkdir -p /var/www/html $EXEC_PREFIX chown -R www-data:www-data /var/www/html 2>/dev/null || true pct push $VMID "$FRONTEND_SOURCE" /var/www/html/index.html 2>/dev/null || true $EXEC_PREFIX chown www-data:www-data /var/www/html/index.html 2>/dev/null || true echo "✅ Frontend deployed" echo "" # Step 3: Nginx config (location /api/ -> 4000) echo "=== Step 3: Configuring nginx ===" $EXEC_PREFIX bash << 'NGINX_EOF' set -e cat > /etc/nginx/sites-available/blockscout << 'NGINX_CONF' # 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; } 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 *; } location /token-aggregation/api/v1/ { proxy_pass http://192.168.11.140:3001/api/v1/; 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 60s; add_header Access-Control-Allow-Origin *; } location = /api/config/token-list { default_type application/json; add_header Access-Control-Allow-Origin *; add_header Cache-Control "public, max-age=3600"; alias /var/www/html/config/DUAL_CHAIN_TOKEN_LIST.tokenlist.json; } location = /api/config/networks { default_type application/json; add_header Access-Control-Allow-Origin *; add_header Cache-Control "public, max-age=3600"; alias /var/www/html/config/DUAL_CHAIN_NETWORKS.json; } location = / { root /var/www/html; try_files /index.html =404; } 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_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; 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; location = / { root /var/www/html; try_files /index.html =404; } location ~ ^/(address|tx|block|token|tokens|blocks|transactions|bridge|weth|liquidity|watchlist|nft|home|analytics|operator|more|pools)(/|$) { root /var/www/html; try_files /index.html =404; add_header Cache-Control "no-store, no-cache, must-revalidate"; } 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"; } 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"; } location /token-aggregation/api/v1/ { proxy_pass http://192.168.11.140:3001/api/v1/; 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 60s; add_header Access-Control-Allow-Origin *; } } NGINX_CONF ln -sf /etc/nginx/sites-available/blockscout /etc/nginx/sites-enabled/blockscout 2>/dev/null || true nginx -t 2>/dev/null && systemctl reload nginx 2>/dev/null || systemctl restart nginx 2>/dev/null || true echo "✅ Nginx configured and reloaded" NGINX_EOF echo "" # Step 4: Wait for Blockscout on port 4000 echo "=== Step 4: Waiting for Blockscout API (port 4000) ===" WAIT_MAX="${BLOCKSCOUT_WAIT_MAX:-45}" WAIT_DONE=0 while [ $WAIT_DONE -lt $WAIT_MAX ]; do if $EXEC_PREFIX curl -sS -f -o /dev/null -w "%{http_code}" --connect-timeout 3 http://127.0.0.1:4000/api/v2/stats 2>/dev/null | grep -q 200; then echo "✅ Blockscout API responding" break fi sleep 5 WAIT_DONE=$((WAIT_DONE + 5)) echo " ... waiting (${WAIT_DONE}s)" done if [ $WAIT_DONE -ge $WAIT_MAX ]; then echo "⚠️ Blockscout did not respond within ${WAIT_MAX}s. Continuing verification anyway." fi echo "" # Step 5: Verify echo "=== Step 5: Verification ===" BASE_URL="${EXPLORER_BASE_URL:-https://explorer.d-bis.org}" VERIFY_SCRIPT="$SCRIPT_DIR/verify-explorer-api-access.sh" [ -f /tmp/verify-explorer-api-access.sh ] && VERIFY_SCRIPT="/tmp/verify-explorer-api-access.sh" if [ -f "$VERIFY_SCRIPT" ]; then bash "$VERIFY_SCRIPT" "$BASE_URL" || true else echo "Verification script not found; manual check:" echo " curl -sS -o /dev/null -w '%{http_code}' $BASE_URL/api/v2/stats" fi echo "" echo "==============================================" echo "Complete. Test: curl -I $BASE_URL/api/v2/stats" echo "=============================================="