Files
proxmox/scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh
defiQUG e4c9dda0fd
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
chore: update submodule references and documentation
- Marked submodules ai-mcp-pmm-controller, explorer-monorepo, and smom-dbis-138 as dirty to reflect recent changes.
- Updated documentation to clarify operator script usage, including dotenv loading and task execution instructions.
- Enhanced the README and various index files to provide clearer navigation and task completion guidance.

Made-with: Cursor
2026-03-04 02:03:08 -08:00

259 lines
13 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Load IP configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
# Update existing NPMplus proxy hosts via API with correct VMIDs and IPs
# This script updates existing proxy hosts, not creates new ones
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Preserve NPM credentials from environment so "export NPM_PASSWORD=...; ./script" works
_orig_npm_url="${NPM_URL:-}"
_orig_npm_email="${NPM_EMAIL:-}"
_orig_npm_password="${NPM_PASSWORD:-}"
# Load dotenv: repo root .env then smom-dbis-138/.env (operator creds)
if [ -f "$PROJECT_ROOT/.env" ]; then
set +u
# shellcheck source=/dev/null
source "$PROJECT_ROOT/.env"
set -u
fi
if [ -f "$PROJECT_ROOT/smom-dbis-138/.env" ]; then
set +u
# shellcheck source=/dev/null
source "$PROJECT_ROOT/smom-dbis-138/.env"
set -u
fi
[ -n "$_orig_npm_url" ] && NPM_URL="$_orig_npm_url"
[ -n "$_orig_npm_email" ] && NPM_EMAIL="$_orig_npm_email"
[ -n "$_orig_npm_password" ] && NPM_PASSWORD="$_orig_npm_password"
[ -f "$PROJECT_ROOT/config/ip-addresses.conf" ] && source "$PROJECT_ROOT/config/ip-addresses.conf" 2>/dev/null || true
# Default .167: NPMplus (VMID 10233) reachable on ${IP_NPMPLUS:-${IP_NPMPLUS:-192.168.11.167}}:81; set NPM_URL in .env to override
NPM_URL="${NPM_URL:-https://${IP_NPMPLUS}:81}"
NPM_EMAIL="${NPM_EMAIL:-nsatoshi2007@hotmail.com}"
NPM_PASSWORD="${NPM_PASSWORD:-}"
if [ -z "$NPM_PASSWORD" ]; then
echo "❌ NPM_PASSWORD is required. Set it in .env or export NPM_PASSWORD=..."
echo " Example: echo 'NPM_PASSWORD=your-password' >> $PROJECT_ROOT/.env"
exit 1
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🔄 Updating NPMplus Proxy Hosts via API"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Connection check (NPMplus is on LAN 192.168.11.x). Try alternate IP if .166/.167 unreachable.
echo "🔐 Authenticating to NPMplus..."
if ! curl -s -k -o /dev/null --connect-timeout 5 "$NPM_URL/" 2>/dev/null; then
alt_url=""
if [[ "$NPM_URL" == *"192.168.11.166"* ]]; then
alt_url="${NPM_URL//192.168.11.166/192.168.11.167}"
elif [[ "$NPM_URL" == *"192.168.11.167"* ]]; then
alt_url="${NPM_URL//192.168.11.167/192.168.11.166}"
fi
if [ -n "$alt_url" ] && curl -s -k -o /dev/null --connect-timeout 5 "$alt_url/" 2>/dev/null; then
NPM_URL="$alt_url"
echo " Using alternate NPMplus URL: $NPM_URL"
else
echo "❌ Cannot connect to NPMplus at $NPM_URL"
[ -n "$alt_url" ] && echo " Tried alternate: $alt_url"
echo " Run this script from a host on the same LAN as NPMplus (e.g. 192.168.11.x). Ensure container 10233 is running."
exit 1
fi
fi
AUTH_JSON=$(jq -n --arg identity "$NPM_EMAIL" --arg secret "$NPM_PASSWORD" '{identity:$identity,secret:$secret}')
TOKEN_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/tokens" \
-H "Content-Type: application/json" \
-d "$AUTH_JSON")
TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.token // empty' 2>/dev/null || echo "")
if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
ERROR_MSG=$(echo "$TOKEN_RESPONSE" | jq -r '.message // .error.message // .error // "Unknown error"' 2>/dev/null || echo "")
echo "❌ Authentication failed: ${ERROR_MSG:-No token in response}"
# Show response (first 300 chars) to help debug
RESP_PREVIEW=$(echo "$TOKEN_RESPONSE" | head -c 300)
if [ -n "$RESP_PREVIEW" ]; then
echo " Response: $RESP_PREVIEW"
fi
exit 1
fi
echo "✅ Authentication successful"
echo ""
# Get all proxy hosts
echo "📋 Fetching existing proxy hosts..."
PROXY_HOSTS_JSON=$(curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts" \
-H "Authorization: Bearer $TOKEN")
if [ $? -ne 0 ]; then
echo "❌ Failed to fetch proxy hosts"
exit 1
fi
# Function to add proxy host (POST) when domain does not exist
add_proxy_host() {
local domain=$1
local forward_host=$2
local forward_port=$3
local websocket=$4
local block_exploits=${5:-false}
local payload
payload=$(jq -n \
--arg domain "$domain" \
--arg host "$forward_host" \
--argjson port "$forward_port" \
--argjson ws "$websocket" \
--argjson block_exploits "$([ "$block_exploits" = "true" ] && echo true || echo false)" \
'{
domain_names: [$domain],
forward_scheme: "http",
forward_host: $host,
forward_port: $port,
allow_websocket_upgrade: $ws,
block_exploits: $block_exploits,
certificate_id: null,
ssl_forced: false
}' 2>/dev/null)
if [ -z "$payload" ]; then
echo " ❌ Failed to build payload for $domain"
return 1
fi
local resp
resp=$(curl -s -k -X POST "$NPM_URL/api/nginx/proxy-hosts" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$payload" 2>/dev/null)
local id
id=$(echo "$resp" | jq -r '.id // empty' 2>/dev/null)
if [ -n "$id" ] && [ "$id" != "null" ]; then
echo " ✅ Added: $domain -> http://${forward_host}:${forward_port} (WebSocket: $websocket)"
return 0
else
local err
err=$(echo "$resp" | jq -r '.message // .error // "unknown"' 2>/dev/null)
echo " ❌ Add failed for $domain: $err"
return 1
fi
}
# Function to update proxy host
# block_exploits: set false for RPC hosts (JSON-RPC uses POST to /; block_exploits can cause 405)
update_proxy_host() {
local domain=$1
local target=$2
local websocket=$3
local block_exploits=${4:-true}
# Parse target URL
local scheme=$(echo "$target" | sed -E 's|^([^:]+):.*|\1|')
local hostname=$(echo "$target" | sed -E 's|^[^/]+//([^:]+):.*|\1|')
local port=$(echo "$target" | sed -E 's|^[^:]+://[^:]+:([0-9]+).*|\1|')
# Handle https URLs
if [[ "$target" == https://* ]]; then
scheme="https"
hostname=$(echo "$target" | sed -E 's|^https://([^:]+):.*|\1|')
port=$(echo "$target" | sed -E 's|^https://[^:]+:([0-9]+).*|\1|' || echo "443")
fi
# Get host ID - domain_names is an array in the API response
HOST_ID=$(echo "$PROXY_HOSTS_JSON" | jq -r ".[] | select(.domain_names | type == \"array\") | select(.domain_names[] == \"$domain\") | .id" 2>/dev/null | head -n1 || echo "")
if [ -z "$HOST_ID" ] || [ "$HOST_ID" = "null" ]; then
echo "⚠️ Domain $domain not found (skipping)"
return 1
fi
echo "📋 Updating $domain (ID: $HOST_ID)..."
# Create minimal update payload - NPMplus API only accepts specific fields
# block_exploits must be false for RPC so POST to / is allowed (JSON-RPC)
BLOCK_EXPLOITS_JSON="false"
[ "$block_exploits" = "true" ] && BLOCK_EXPLOITS_JSON="true"
UPDATE_PAYLOAD=$(jq -n \
--arg scheme "$scheme" \
--arg hostname "$hostname" \
--argjson port "$(echo "$port" | sed 's/[^0-9]//g')" \
--argjson websocket "$websocket" \
--argjson block_exploits "$BLOCK_EXPLOITS_JSON" \
'{
forward_scheme: $scheme,
forward_host: $hostname,
forward_port: $port,
allow_websocket_upgrade: $websocket,
block_exploits: $block_exploits
}' 2>/dev/null || echo "")
UPDATE_RESPONSE=$(curl -s -k -X PUT "$NPM_URL/api/nginx/proxy-hosts/$HOST_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$UPDATE_PAYLOAD")
UPDATE_ID=$(echo "$UPDATE_RESPONSE" | jq -r '.id // empty' 2>/dev/null || echo "")
if [ -n "$UPDATE_ID" ] && [ "$UPDATE_ID" != "null" ]; then
echo " ✅ Updated: $scheme://$hostname:$port (WebSocket: $websocket)"
return 0
else
ERROR=$(echo "$UPDATE_RESPONSE" | jq -r '.error.message // .error // "Unknown error"' 2>/dev/null || echo "$UPDATE_RESPONSE")
echo " ❌ Failed: $ERROR"
return 1
fi
}
# Update all domains
updated_count=0
failed_count=0
# Blockscout - Port 80 (nginx serves web UI, proxies /api/* to 4000 internally)
update_proxy_host "explorer.d-bis.org" "http://${IP_BLOCKSCOUT}:80" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
# RPC hosts: block_exploits must be false so POST to / works (JSON-RPC)
update_proxy_host "rpc-http-pub.d-bis.org" "http://${RPC_PUBLIC_1}:8545" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "rpc-ws-pub.d-bis.org" "http://${RPC_PUBLIC_1}:8546" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "rpc-http-prv.d-bis.org" "http://${RPC_CORE_1}:8545" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "rpc-ws-prv.d-bis.org" "http://${RPC_CORE_1}:8546" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
# RPC Core-2 (Nathan) is on the THIRD NPMplus (192.168.11.169) — use add-rpc-core-2-npmplus-proxy.sh and update-npmplus-alltra-hybx-proxy-hosts.sh
update_proxy_host "rpc.public-0138.defi-oracle.io" "https://${RPC_THIRDWEB_PRIMARY}:443" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
# rpc.defi-oracle.io / wss.defi-oracle.io → same backend as rpc-http-pub / rpc-ws-pub (VMID 2201)
update_proxy_host "rpc.defi-oracle.io" "http://${RPC_PUBLIC_1}:8545" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "wss.defi-oracle.io" "http://${RPC_PUBLIC_1}:8546" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
# rpc.d-bis.org / rpc2.d-bis.org and WS variants → VMID 2201 (besu-rpc-public-1)
update_proxy_host "rpc.d-bis.org" "http://${RPC_PUBLIC_1}:8545" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "rpc2.d-bis.org" "http://${RPC_PUBLIC_1}:8545" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "ws.rpc.d-bis.org" "http://${RPC_PUBLIC_1}:8546" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "ws.rpc2.d-bis.org" "http://${RPC_PUBLIC_1}:8546" true false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
# Fireblocks-dedicated RPC (VMID 2301)
update_proxy_host "rpc-fireblocks.d-bis.org" "http://${RPC_FIREBLOCKS_1:-${RPC_PRIVATE_1}}:8545" true false && updated_count=$((updated_count + 1)) || { add_proxy_host "rpc-fireblocks.d-bis.org" "${RPC_FIREBLOCKS_1:-${RPC_PRIVATE_1}}" 8545 true false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
update_proxy_host "ws.rpc-fireblocks.d-bis.org" "http://${RPC_FIREBLOCKS_1:-${RPC_PRIVATE_1}}:8546" true false && updated_count=$((updated_count + 1)) || { add_proxy_host "ws.rpc-fireblocks.d-bis.org" "${RPC_FIREBLOCKS_1:-${RPC_PRIVATE_1}}" 8546 true false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
update_proxy_host "dbis-admin.d-bis.org" "http://${IP_DBIS_FRONTEND:-192.168.11.130}:80" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "dbis-api.d-bis.org" "http://${IP_DBIS_API:-192.168.11.155}:3000" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "dbis-api-2.d-bis.org" "http://${IP_DBIS_API_2:-192.168.11.156}:3000" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "secure.d-bis.org" "http://${IP_DBIS_FRONTEND:-192.168.11.130}:80" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
# MIM4U - VMID 7810 (mim-web-1) @ ${IP_MIM_WEB:-192.168.11.37} - Web Frontend serves main site and proxies /api/* to 7811
update_proxy_host "mim4u.org" "http://${IP_MIM_WEB:-192.168.11.37}:80" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "www.mim4u.org" "http://${IP_MIM_WEB:-192.168.11.37}:80" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "secure.mim4u.org" "http://${IP_MIM_WEB:-192.168.11.37}:80" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
update_proxy_host "training.mim4u.org" "http://${IP_MIM_WEB:-192.168.11.37}:80" false && updated_count=$((updated_count + 1)) || failed_count=$((failed_count + 1))
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📊 Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Updated: $updated_count"
echo "❌ Failed: $failed_count"
echo ""