#!/usr/bin/env bash # Install and configure Nginx reverse proxy for Blockscout Explorer # Usage: ./install-nginx-blockscout.sh [VMID] [IP] # Defaults: VMID=5000, IP=192.168.11.140 set -euo pipefail VMID="${1:-5000}" IP="${2:-192.168.11.140}" DOMAIN="${DOMAIN:-explorer.d-bis.org}" BLOCKSCOUT_PORT="${BLOCKSCOUT_PORT:-4000}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}" # Function to execute command in container exec_container() { local cmd="$1" # Check if we're already on the Proxmox host (command exists locally) if command -v pct >/dev/null 2>&1; then # Running directly on Proxmox host - use pct directly pct exec $VMID -- bash -c "$cmd" 2>/dev/null || echo "" else ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $VMID -- bash -c '$cmd'" 2>/dev/null || echo "" fi } log_info "Installing Nginx for Blockscout Explorer (VMID: $VMID, IP: $IP)" # Check if container exists and is running log_info "Checking container status..." if command -v pct >/dev/null 2>&1; then # Running directly on Proxmox host CONTAINER_STATUS=$(pct status $VMID 2>/dev/null | awk '{print $2}' || echo 'missing') if [ "$CONTAINER_STATUS" != "running" ]; then log_warn "Container is not running. Starting container..." pct start $VMID || { log_error "Failed to start container $VMID" exit 1 } sleep 5 fi else CONTAINER_STATUS=$(ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct status $VMID 2>/dev/null | awk '{print \$2}' || echo 'missing'") if [ "$CONTAINER_STATUS" != "running" ]; then log_warn "Container is not running. Starting container..." ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct start $VMID" || { log_error "Failed to start container $VMID" exit 1 } sleep 5 fi fi log_success "Container is running" # Install Nginx log_info "Installing Nginx..." exec_container "export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq nginx" || { log_error "Failed to install Nginx" exit 1 } log_success "Nginx installed" # Create SSL directory log_info "Creating SSL directory..." exec_container "mkdir -p /etc/nginx/ssl" # Generate self-signed certificate (can be replaced with Let's Encrypt later) log_info "Generating self-signed SSL certificate..." exec_container "openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /etc/nginx/ssl/blockscout.key \ -out /etc/nginx/ssl/blockscout.crt \ -subj '/CN=$DOMAIN/O=Blockscout Explorer/C=US' 2>/dev/null" || { log_warn "SSL certificate generation may have failed, continuing..." } # Create Nginx configuration log_info "Creating Nginx configuration..." # Create config file content NGINX_CONFIG_CONTENT=$(cat <<'NGINX_EOF' # HTTP server - redirect to HTTPS server { listen 80; listen [::]:80; server_name $DOMAIN explorer.d-bis.org blockscout-1 $IP; # Allow Let's Encrypt ACME challenges location /.well-known/acme-challenge/ { root /var/www/html; } # Redirect all other traffic to HTTPS location / { return 301 https://\$host\$request_uri; } } # HTTPS server - Blockscout Explorer server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name $DOMAIN explorer.d-bis.org blockscout-1 $IP; # SSL configuration ssl_certificate /etc/nginx/ssl/blockscout.crt; ssl_certificate_key /etc/nginx/ssl/blockscout.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # 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; # Logging access_log /var/log/nginx/blockscout-access.log; error_log /var/log/nginx/blockscout-error.log; # Increase timeouts for Blockscout requests proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; send_timeout 300s; # Client body size (for large contract verification uploads) client_max_body_size 50M; # Blockscout Explorer endpoint location / { proxy_pass http://127.0.0.1:$BLOCKSCOUT_PORT; proxy_http_version 1.1; # Headers 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_set_header Connection ""; # Buffer settings proxy_buffering off; proxy_request_buffering off; # WebSocket support (for Blockscout real-time updates) proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection \$connection_upgrade; } # Health check endpoint location /health { access_log off; proxy_pass http://127.0.0.1:$BLOCKSCOUT_PORT/api/v2/status; proxy_set_header Host \$host; add_header Content-Type application/json; } # API endpoint (for Blockscout API) location /api/ { proxy_pass http://127.0.0.1:$BLOCKSCOUT_PORT; 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; } } # WebSocket upgrade mapping map \$http_upgrade \$connection_upgrade { default upgrade; '' close; } NGINX_EOF ) # Write config file to container if command -v pct >/dev/null 2>&1; then # Running directly on Proxmox host echo "$NGINX_CONFIG_CONTENT" | pct exec $VMID -- bash -c "cat > /etc/nginx/sites-available/blockscout" pct exec $VMID -- bash -c "ln -sf /etc/nginx/sites-available/blockscout /etc/nginx/sites-enabled/ && rm -f /etc/nginx/sites-enabled/default" pct exec $VMID -- nginx -t pct exec $VMID -- systemctl enable nginx pct exec $VMID -- systemctl restart nginx else echo "$NGINX_CONFIG_CONTENT" | ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $VMID -- bash -c 'cat > /etc/nginx/sites-available/blockscout'" ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $VMID -- bash -c 'ln -sf /etc/nginx/sites-available/blockscout /etc/nginx/sites-enabled/ && rm -f /etc/nginx/sites-enabled/default'" ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $VMID -- nginx -t" ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $VMID -- systemctl enable nginx" ssh -o StrictHostKeyChecking=no root@"$PROXMOX_HOST" "pct exec $VMID -- systemctl restart nginx" fi if [ $? -eq 0 ]; then log_success "Nginx configuration created and enabled" else log_error "Failed to create Nginx configuration" exit 1 fi # Verify Nginx is running log_info "Verifying Nginx status..." if exec_container "systemctl is-active nginx >/dev/null 2>&1"; then log_success "Nginx service is active" else log_error "Nginx service is not active" exit 1 fi # Check if ports are listening log_info "Checking listening ports..." PORTS=$(exec_container "ss -tlnp 2>&1 | grep -E ':80|:443' || echo ''") if echo "$PORTS" | grep -q ':80'; then log_success "Port 80 is listening" else log_warn "Port 80 may not be listening" fi if echo "$PORTS" | grep -q ':443'; then log_success "Port 443 is listening" else log_warn "Port 443 may not be listening" fi # Test Blockscout connectivity log_info "Testing Blockscout connectivity..." BLOCKSCOUT_TEST=$(exec_container "timeout 5 curl -s http://127.0.0.1:$BLOCKSCOUT_PORT/api/v2/status 2>&1 || echo 'FAILED'") if echo "$BLOCKSCOUT_TEST" | grep -q "success\|chain_id"; then log_success "Blockscout is responding on port $BLOCKSCOUT_PORT" else log_warn "Blockscout may not be running on port $BLOCKSCOUT_PORT" log_info "Response: $BLOCKSCOUT_TEST" fi # Test through Nginx log_info "Testing Nginx proxy..." NGINX_TEST=$(exec_container "timeout 5 curl -k -s http://127.0.0.1/health 2>&1 || echo 'FAILED'") if echo "$NGINX_TEST" | grep -q "success\|chain_id"; then log_success "Nginx proxy is working!" else log_warn "Nginx proxy test failed (Blockscout may still be starting)" log_info "Response: $NGINX_TEST" fi echo "" log_success "Nginx installation and configuration complete!" echo "" log_info "Configuration Summary:" log_info " - HTTP: http://$IP:80 (redirects to HTTPS)" log_info " - HTTPS: https://$IP:443 (proxies to localhost:$BLOCKSCOUT_PORT)" log_info " - Domain: $DOMAIN" log_info "" log_info "Next steps:" log_info " 1. Configure Cloudflare DNS/tunnel for $DOMAIN" log_info " 2. Verify Blockscout service is running: pct exec $VMID -- systemctl status blockscout" log_info " 3. Test: curl -k https://$IP"