- Reject non-https, paths, and injection-prone chars in advanced_config 301 targets - E2E list: phoenix marketing note, the-order HAProxy remediation, 2026-03-27 passes - AGENTS.md: scoped Cloudflare token pointer; smom-dbis-138 dotenv load note - .env.master.example: DNS script flags and scoped token guidance Made-with: Cursor
414 lines
29 KiB
Bash
Executable File
414 lines
29 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Security: do not use `bash -x` or `curl -v` when debugging auth in production — logs may capture secrets.
|
|
# Auth failures: only a short error message is printed by default. For a redacted JSON snippet set NPM_DEBUG_AUTH=1.
|
|
set -euo pipefail
|
|
|
|
# Repo root (…/proxmox) — same as second block below; load IPs once from the right path
|
|
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.
|
|
# PUT payload includes only forward_* / websocket / block_exploits — existing certificate_id and ssl_forced are preserved by NPMplus.
|
|
|
|
set -e
|
|
|
|
# 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: NPMplus (VMID 10233) — IP_NPMPLUS from config/ip-addresses.conf (prefer eth1 / .167); override with NPM_URL in .env
|
|
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 ""
|
|
|
|
# NPMplus API can stall indefinitely without --max-time (override e.g. NPM_CURL_MAX_TIME=300)
|
|
NPM_CURL_MAX_TIME="${NPM_CURL_MAX_TIME:-120}"
|
|
# -L: port 81 often 301s HTTP→HTTPS; POST /api/tokens without -L returns 400 "Payload is undefined"
|
|
curl_npm() { curl -s -k -L --connect-timeout 10 --max-time "$NPM_CURL_MAX_TIME" "$@"; }
|
|
|
|
# Connection check (NPMplus is on LAN 192.168.11.x). Try HTTP if HTTPS fails; try alternate IP .166/.167 if unreachable.
|
|
echo "🔐 Authenticating to NPMplus..."
|
|
try_connect() { curl -s -k -L -o /dev/null --connect-timeout 5 --max-time 15 "$1" 2>/dev/null; }
|
|
if ! try_connect "$NPM_URL/"; then
|
|
# Try HTTP instead of HTTPS (NPM admin often listens on HTTP only on port 81)
|
|
http_url="${NPM_URL/https:/http:}"
|
|
if try_connect "$http_url/"; then
|
|
NPM_URL="$http_url"
|
|
echo " Using HTTP (HTTPS timed out): $NPM_URL"
|
|
else
|
|
alt_url=""
|
|
if [[ "$NPM_URL" == *"${IP_NPMPLUS_ETH0}"* ]]; then
|
|
alt_url="https://${IP_NPMPLUS}:81"
|
|
elif [[ "$NPM_URL" == *"${IP_NPMPLUS}"* ]] || [[ -n "${IP_NPMPLUS_ETH1:-}" && "$NPM_URL" == *"${IP_NPMPLUS_ETH1}"* ]]; then
|
|
alt_url="https://${IP_NPMPLUS_ETH0}:81"
|
|
fi
|
|
connected=""
|
|
if [ -n "$alt_url" ] && try_connect "$alt_url/"; then connected="$alt_url"; fi
|
|
if [ -z "$connected" ] && [ -n "$alt_url" ] && try_connect "${alt_url/https:/http:}/"; then connected="${alt_url/https:/http:}"; fi
|
|
if [ -n "$connected" ]; then
|
|
NPM_URL="$connected"
|
|
echo " Using alternate NPMplus URL: $NPM_URL"
|
|
else
|
|
echo "❌ Cannot connect to NPMplus at $NPM_URL"
|
|
[ -n "$alt_url" ] && echo " Tried alternate: $alt_url and ${alt_url/https:/http:}"
|
|
echo " Try in browser: http://${IP_NPMPLUS}:81 (not https). If not on LAN, use SSH tunnel: ssh -L 8181:${IP_NPMPLUS}:81 -N root@${PROXMOX_HOST_R630_01} then http://127.0.0.1:8181"
|
|
echo " Run this script from a host on the same LAN as NPMplus. Ensure container 10233 is running."
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
AUTH_JSON=$(jq -n --arg identity "$NPM_EMAIL" --arg secret "$NPM_PASSWORD" '{identity:$identity,secret:$secret}')
|
|
TOKEN_RESPONSE=$(curl_npm -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}"
|
|
if [ "${NPM_DEBUG_AUTH:-0}" = "1" ]; then
|
|
# Strip .token from body before preview (never print bearer tokens)
|
|
RESP_PREVIEW=$(echo "$TOKEN_RESPONSE" | jq -c 'del(.token) | del(.data)' 2>/dev/null | head -c 300)
|
|
[ -z "$RESP_PREVIEW" ] && RESP_PREVIEW=$(echo "$TOKEN_RESPONSE" | head -c 200)
|
|
echo " Debug (NPM_DEBUG_AUTH=1, token field stripped if jq OK): $RESP_PREVIEW"
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ Authentication successful"
|
|
echo ""
|
|
|
|
# Get all proxy hosts
|
|
echo "📋 Fetching existing proxy hosts..."
|
|
PROXY_HOSTS_JSON=$(curl_npm -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
|
|
|
|
# Match proxy host id by domain (case-insensitive). Avoids "not found" when NPM stores different casing.
|
|
resolve_proxy_host_id() {
|
|
local domain="$1"
|
|
local json="${2:-$PROXY_HOSTS_JSON}"
|
|
echo "$json" | jq -r --arg d "$domain" '
|
|
.[] | select(.domain_names | type == "array") |
|
|
select(any(.domain_names[]; (. | tostring | ascii_downcase) == ($d | ascii_downcase))) |
|
|
.id' 2>/dev/null | head -n1
|
|
}
|
|
|
|
# www → apex redirect: only https://hostname[:port] (no path/query); rejects characters that could break nginx advanced_config.
|
|
validate_canonical_https_redirect() {
|
|
local url="$1"
|
|
local ctx="${2:-canonical_https}"
|
|
if [[ "$url" != https://* ]]; then
|
|
echo " ❌ $ctx: canonical_https must start with https:// (got: $url)"
|
|
return 1
|
|
fi
|
|
if [[ "$url" == *$'\n'* || "$url" == *$'\r'* || "$url" == *' '* || "$url" == *';'* || "$url" == *'$'* || "$url" == *'`'* ]]; then
|
|
echo " ❌ $ctx: canonical_https contains forbidden characters (no spaces, semicolons, dollar, backticks)"
|
|
return 1
|
|
fi
|
|
local rest="${url#https://}"
|
|
if [[ "$rest" == */* ]]; then
|
|
echo " ❌ $ctx: canonical_https must not include a path (got: $url)"
|
|
return 1
|
|
fi
|
|
if ! [[ "$rest" =~ ^[a-zA-Z0-9._-]+(:[0-9]{1,5})?$ ]]; then
|
|
echo " ❌ $ctx: canonical_https must be https://hostname or https://hostname:port (got: $url)"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Function to add proxy host (POST) when domain does not exist
|
|
# Optional 6th arg: canonical HTTPS apex for www-style hosts (sets advanced_config 301 → apex$request_uri)
|
|
add_proxy_host() {
|
|
local domain=$1
|
|
local forward_host=$2
|
|
local forward_port=$3
|
|
local websocket=$4
|
|
local block_exploits=${5:-false}
|
|
local canonical_https="${6:-}"
|
|
local adv_line=""
|
|
if [ -n "$canonical_https" ] && ! validate_canonical_https_redirect "$canonical_https" "add_proxy_host($domain)"; then
|
|
return 1
|
|
fi
|
|
if [ -n "$canonical_https" ]; then
|
|
adv_line="return 301 ${canonical_https}\$request_uri;"
|
|
fi
|
|
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)" \
|
|
--arg adv "$adv_line" \
|
|
'{
|
|
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
|
|
} + (if $adv != "" then {advanced_config: $adv} else {} end)' 2>/dev/null)
|
|
if [ -z "$payload" ]; then
|
|
echo " ❌ Failed to build payload for $domain"
|
|
return 1
|
|
fi
|
|
local resp
|
|
resp=$(curl_npm -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
|
|
if [ -n "$canonical_https" ]; then
|
|
echo " ✅ Added: $domain -> http://${forward_host}:${forward_port} (WebSocket: $websocket) + 301 → ${canonical_https}\$request_uri"
|
|
else
|
|
echo " ✅ Added: $domain -> http://${forward_host}:${forward_port} (WebSocket: $websocket)"
|
|
fi
|
|
return 0
|
|
else
|
|
local err
|
|
err=$(echo "$resp" | jq -r '.message // .error // "unknown"' 2>/dev/null)
|
|
echo " ❌ Add failed for $domain: $err"
|
|
if echo "$err" | grep -qiE 'already|in use|exist|duplicate|unique'; then
|
|
echo " ↪ Host likely exists; refreshing list and attempting PUT update..."
|
|
PROXY_HOSTS_JSON=$(curl_npm -X GET "$NPM_URL/api/nginx/proxy-hosts" \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
if update_proxy_host "$domain" "http://${forward_host}:${forward_port}" "$websocket" "$block_exploits" "$canonical_https"; then
|
|
echo " ✅ Updated after duplicate-create error: $domain"
|
|
return 0
|
|
fi
|
|
fi
|
|
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)
|
|
# Optional 5th arg: canonical HTTPS URL (no path) — sets advanced_config to 301 redirect (www → apex)
|
|
update_proxy_host() {
|
|
local domain=$1
|
|
local target=$2
|
|
local websocket=$3
|
|
local block_exploits=${4:-true}
|
|
local canonical_https="${5:-}"
|
|
if [ -n "$canonical_https" ] && ! validate_canonical_https_redirect "$canonical_https" "update_proxy_host($domain)"; then
|
|
return 1
|
|
fi
|
|
|
|
# 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
|
|
|
|
# Reject bad parses (e.g. https://:443 when forward IP env is empty) — NPM returns errors without .id and jq message is empty.
|
|
if [[ -z "$hostname" || "$hostname" == *"://"* || "$hostname" == *"/"* ]]; then
|
|
echo " ❌ Invalid forward target for $domain (check env / ip-addresses.conf): $target → host=[$hostname]"
|
|
return 1
|
|
fi
|
|
port="${port//[^0-9]/}"
|
|
if [[ -z "$port" || "$port" -lt 1 || "$port" -gt 65535 ]]; then
|
|
echo " ❌ Invalid forward port for $domain: $target (parsed port=$port)"
|
|
return 1
|
|
fi
|
|
|
|
# Get host ID (case-insensitive); refresh once if missing (stale list / race with other writers)
|
|
HOST_ID=$(resolve_proxy_host_id "$domain" "$PROXY_HOSTS_JSON")
|
|
if [ -z "$HOST_ID" ] || [ "$HOST_ID" = "null" ]; then
|
|
echo "📋 Refreshing proxy host list (retry lookup for $domain)..."
|
|
PROXY_HOSTS_JSON=$(curl_npm -X GET "$NPM_URL/api/nginx/proxy-hosts" \
|
|
-H "Authorization: Bearer $TOKEN")
|
|
HOST_ID=$(resolve_proxy_host_id "$domain" "$PROXY_HOSTS_JSON")
|
|
fi
|
|
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); explicit false fixes 405
|
|
local be_json="false"
|
|
[ "$block_exploits" = "true" ] && be_json="true"
|
|
local adv_line=""
|
|
if [ -n "$canonical_https" ]; then
|
|
adv_line="return 301 ${canonical_https}\$request_uri;"
|
|
fi
|
|
UPDATE_PAYLOAD=$(jq -n \
|
|
--arg scheme "$scheme" \
|
|
--arg hostname "$hostname" \
|
|
--argjson port "$(echo "$port" | sed 's/[^0-9]//g' || echo "80")" \
|
|
--argjson websocket "$websocket" \
|
|
--argjson block_exploits "$be_json" \
|
|
--arg adv "$adv_line" \
|
|
'{
|
|
forward_scheme: $scheme,
|
|
forward_host: $hostname,
|
|
forward_port: $port,
|
|
allow_websocket_upgrade: $websocket,
|
|
block_exploits: $block_exploits
|
|
} + (if $adv != "" then {advanced_config: $adv} else {} end)' 2>/dev/null || echo "")
|
|
|
|
UPDATE_RESPONSE=$(curl_npm -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
|
|
if [ -n "$canonical_https" ]; then
|
|
echo " ✅ Updated: $scheme://$hostname:$port (WebSocket: $websocket) + 301 → ${canonical_https}\$request_uri"
|
|
else
|
|
echo " ✅ Updated: $scheme://$hostname:$port (WebSocket: $websocket)"
|
|
fi
|
|
return 0
|
|
else
|
|
ERROR=$(echo "$UPDATE_RESPONSE" | jq -r '.error.message // .message // .error // empty' 2>/dev/null || echo "")
|
|
[ -z "$ERROR" ] && ERROR=$(echo "$UPDATE_RESPONSE" | head -c 400 | tr -d '\r\n')
|
|
[ -z "$ERROR" ] && ERROR="(empty API response — timeout or connection error; try NPM_CURL_MAX_TIME=300)"
|
|
echo " ❌ Failed: $ERROR"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Update all domains
|
|
updated_count=0
|
|
failed_count=0
|
|
|
|
# Blockscout / SolaceScanScout (VMID 5000) - 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))
|
|
update_proxy_host "blockscout.defi-oracle.io" "http://${IP_BLOCKSCOUT}:80" false && updated_count=$((updated_count + 1)) || { add_proxy_host "blockscout.defi-oracle.io" "${IP_BLOCKSCOUT}" 80 false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# docs.d-bis.org — same backend as explorer; nginx on VMID 5000 must serve /transaction-explanation/ (see deploy README)
|
|
update_proxy_host "docs.d-bis.org" "http://${IP_BLOCKSCOUT}:80" false && updated_count=$((updated_count + 1)) || { add_proxy_host "docs.d-bis.org" "${IP_BLOCKSCOUT}" 80 false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# RPC hosts: block_exploits must be false so POST to / works (JSON-RPC). Add if missing to avoid 405.
|
|
update_proxy_host "rpc-http-pub.d-bis.org" "http://${RPC_PUBLIC_1}:8545" true false && updated_count=$((updated_count + 1)) || { add_proxy_host "rpc-http-pub.d-bis.org" "${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)) || { add_proxy_host "rpc-ws-pub.d-bis.org" "${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)) || { add_proxy_host "rpc-http-prv.d-bis.org" "${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)) || { add_proxy_host "rpc-ws-prv.d-bis.org" "${RPC_CORE_1}" 8546 true false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# ThirdWeb Admin Core RPC — VMID ${RPC_THIRDWEB_ADMIN_CORE_VMID:-2103} @ ${RPC_THIRDWEB_ADMIN_CORE} (HTTPS + WSS via NPMplus; block_exploits off for JSON-RPC POST)
|
|
RPC_THIRDWEB_ADMIN_CORE="${RPC_THIRDWEB_ADMIN_CORE:-192.168.11.217}"
|
|
update_proxy_host "rpc.tw-core.d-bis.org" "http://${RPC_THIRDWEB_ADMIN_CORE}:8545" true false && updated_count=$((updated_count + 1)) || { add_proxy_host "rpc.tw-core.d-bis.org" "${RPC_THIRDWEB_ADMIN_CORE}" 8545 true false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "wss.tw-core.d-bis.org" "http://${RPC_THIRDWEB_ADMIN_CORE}:8546" true false && updated_count=$((updated_count + 1)) || { add_proxy_host "wss.tw-core.d-bis.org" "${RPC_THIRDWEB_ADMIN_CORE}" 8546 true false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# Catch-all for foo.tw-core.d-bis.org → Besu HTTP JSON-RPC :8545 (exact rpc./wss. hosts above take precedence for nginx server_name)
|
|
update_proxy_host '*.tw-core.d-bis.org' "http://${RPC_THIRDWEB_ADMIN_CORE}:8545" true false && updated_count=$((updated_count + 1)) || { add_proxy_host '*.tw-core.d-bis.org' "${RPC_THIRDWEB_ADMIN_CORE}" 8545 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
|
|
# ThirdWeb / public-0138 edge (VMID 2400 nginx HTTPS) — default IP must match ALL_VMIDS_ENDPOINTS if env is unset
|
|
RPC_THIRDWEB_PRIMARY="${RPC_THIRDWEB_PRIMARY:-192.168.11.240}"
|
|
update_proxy_host "rpc.public-0138.defi-oracle.io" "https://${RPC_THIRDWEB_PRIMARY}:443" true false && updated_count=$((updated_count + 1)) || { sleep 2; echo " ↪ Retry rpc.public-0138.defi-oracle.io after transient NPM/API error..."; 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)) || { add_proxy_host "rpc.defi-oracle.io" "${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)) || { add_proxy_host "wss.defi-oracle.io" "${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); add if missing to fix 405
|
|
update_proxy_host "rpc.d-bis.org" "http://${RPC_PUBLIC_1}:8545" true false && updated_count=$((updated_count + 1)) || { add_proxy_host "rpc.d-bis.org" "${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)) || { add_proxy_host "rpc2.d-bis.org" "${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)) || { add_proxy_host "ws.rpc.d-bis.org" "${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)) || { add_proxy_host "ws.rpc2.d-bis.org" "${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)) || { add_proxy_host "dbis-api-2.d-bis.org" "${IP_DBIS_API_2:-192.168.11.156}" 3000 false true && 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)) || { add_proxy_host "secure.d-bis.org" "${IP_DBIS_FRONTEND:-192.168.11.130}" 80 false true && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# DApp (VMID 5801) — frontend-dapp for Chain 138 bridge
|
|
update_proxy_host "dapp.d-bis.org" "http://${IP_DAPP_LXC:-192.168.11.58}:80" false && updated_count=$((updated_count + 1)) || { add_proxy_host "dapp.d-bis.org" "${IP_DAPP_LXC:-192.168.11.58}" 80 false 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)) || { add_proxy_host "mim4u.org" "${IP_MIM_WEB:-192.168.11.37}" 80 false true && 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)) || { add_proxy_host "www.mim4u.org" "${IP_MIM_WEB:-192.168.11.37}" 80 false true && 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)) || { add_proxy_host "secure.mim4u.org" "${IP_MIM_WEB:-192.168.11.37}" 80 false true && 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)) || { add_proxy_host "training.mim4u.org" "${IP_MIM_WEB:-192.168.11.37}" 80 false true && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# Gov Portals xom-dev (VMID 7804) — public https:// at NPM (LE); upstream HTTP
|
|
IP_GOV_PORTALS_DEV="${IP_GOV_PORTALS_DEV:-192.168.11.54}"
|
|
update_proxy_host "dbis.xom-dev.phoenix.sankofa.nexus" "http://${IP_GOV_PORTALS_DEV}:3001" false && updated_count=$((updated_count + 1)) || { add_proxy_host "dbis.xom-dev.phoenix.sankofa.nexus" "${IP_GOV_PORTALS_DEV}" 3001 false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "iccc.xom-dev.phoenix.sankofa.nexus" "http://${IP_GOV_PORTALS_DEV}:3002" false && updated_count=$((updated_count + 1)) || { add_proxy_host "iccc.xom-dev.phoenix.sankofa.nexus" "${IP_GOV_PORTALS_DEV}" 3002 false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "omnl.xom-dev.phoenix.sankofa.nexus" "http://${IP_GOV_PORTALS_DEV}:3003" false && updated_count=$((updated_count + 1)) || { add_proxy_host "omnl.xom-dev.phoenix.sankofa.nexus" "${IP_GOV_PORTALS_DEV}" 3003 false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "xom.xom-dev.phoenix.sankofa.nexus" "http://${IP_GOV_PORTALS_DEV}:3004" false && updated_count=$((updated_count + 1)) || { add_proxy_host "xom.xom-dev.phoenix.sankofa.nexus" "${IP_GOV_PORTALS_DEV}" 3004 false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# Sankofa portal (Next.js CT 7801) and Phoenix API (Fastify CT 7800) — not Blockscout / SolaceScanScout (that is explorer.d-bis.org / IP_BLOCKSCOUT:80)
|
|
# Public URL policy: https://sankofa.nexus = sovereign technology utility (portal); https://phoenix.sankofa.nexus = Phoenix division (API host; marketing site may share hostname later).
|
|
# www.sankofa.nexus → 301 https://sankofa.nexus$request_uri; www.phoenix → phoenix; www.the-order → the-order (NPM advanced_config).
|
|
IP_SANKOFA_PORTAL="${IP_SANKOFA_PORTAL:-${IP_SERVICE_51:-192.168.11.51}}"
|
|
IP_SANKOFA_PHOENIX_API="${IP_SANKOFA_PHOENIX_API:-${IP_SERVICE_50:-192.168.11.50}}"
|
|
SANKOFA_PORTAL_PORT="${SANKOFA_PORTAL_PORT:-3000}"
|
|
SANKOFA_PHOENIX_API_PORT="${SANKOFA_PHOENIX_API_PORT:-4000}"
|
|
update_proxy_host "sankofa.nexus" "http://${IP_SANKOFA_PORTAL}:${SANKOFA_PORTAL_PORT}" false false && updated_count=$((updated_count + 1)) || { add_proxy_host "sankofa.nexus" "${IP_SANKOFA_PORTAL}" "${SANKOFA_PORTAL_PORT}" false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "www.sankofa.nexus" "http://${IP_SANKOFA_PORTAL}:${SANKOFA_PORTAL_PORT}" false false "https://sankofa.nexus" && updated_count=$((updated_count + 1)) || { add_proxy_host "www.sankofa.nexus" "${IP_SANKOFA_PORTAL}" "${SANKOFA_PORTAL_PORT}" false false "https://sankofa.nexus" && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "phoenix.sankofa.nexus" "http://${IP_SANKOFA_PHOENIX_API}:${SANKOFA_PHOENIX_API_PORT}" false false && updated_count=$((updated_count + 1)) || { add_proxy_host "phoenix.sankofa.nexus" "${IP_SANKOFA_PHOENIX_API}" "${SANKOFA_PHOENIX_API_PORT}" false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "www.phoenix.sankofa.nexus" "http://${IP_SANKOFA_PHOENIX_API}:${SANKOFA_PHOENIX_API_PORT}" false false "https://phoenix.sankofa.nexus" && updated_count=$((updated_count + 1)) || { add_proxy_host "www.phoenix.sankofa.nexus" "${IP_SANKOFA_PHOENIX_API}" "${SANKOFA_PHOENIX_API_PORT}" false false "https://phoenix.sankofa.nexus" && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# Keycloak (CT 7802) — portal SSO; NPM must forward X-Forwarded-* (Keycloak KC_PROXY_HEADERS=xforwarded on upstream)
|
|
IP_KEYCLOAK="${IP_KEYCLOAK:-192.168.11.52}"
|
|
update_proxy_host "keycloak.sankofa.nexus" "http://${IP_KEYCLOAK}:8080" false false && updated_count=$((updated_count + 1)) || { add_proxy_host "keycloak.sankofa.nexus" "${IP_KEYCLOAK}" 8080 false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# the-order.sankofa.nexus — public hostname for the Sovereign Military Order of Malta (OSJ) management portal (secure auth).
|
|
# Application source (operator workstation): repo the_order at ~/projects/the_order (e.g. /home/intlc/projects/the_order).
|
|
# Ideal upstream: VMID 10210 order-haproxy @ IP_ORDER_HAPROXY:80. When HAProxy/order edge is not serving, NPM may 502.
|
|
# Interim default: same Next.js upstream as sankofa.nexus (7801). Switch: THE_ORDER_UPSTREAM_IP=192.168.11.39 THE_ORDER_UPSTREAM_PORT=80.
|
|
# www.the-order.sankofa.nexus → 301 https://the-order.sankofa.nexus$request_uri (same pattern as www.sankofa / www.phoenix).
|
|
IP_ORDER_HAPROXY="${IP_ORDER_HAPROXY:-192.168.11.39}"
|
|
THE_ORDER_UPSTREAM_IP="${THE_ORDER_UPSTREAM_IP:-${IP_SANKOFA_PORTAL}}"
|
|
THE_ORDER_UPSTREAM_PORT="${THE_ORDER_UPSTREAM_PORT:-${SANKOFA_PORTAL_PORT}}"
|
|
# block_exploits false — same policy as sankofa.nexus portal (Next/API-friendly; avoid 405 on some POST paths)
|
|
update_proxy_host "the-order.sankofa.nexus" "http://${THE_ORDER_UPSTREAM_IP}:${THE_ORDER_UPSTREAM_PORT}" false false && updated_count=$((updated_count + 1)) || { add_proxy_host "the-order.sankofa.nexus" "${THE_ORDER_UPSTREAM_IP}" "${THE_ORDER_UPSTREAM_PORT}" false false && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
update_proxy_host "www.the-order.sankofa.nexus" "http://${THE_ORDER_UPSTREAM_IP}:${THE_ORDER_UPSTREAM_PORT}" false false "https://the-order.sankofa.nexus" && updated_count=$((updated_count + 1)) || { add_proxy_host "www.the-order.sankofa.nexus" "${THE_ORDER_UPSTREAM_IP}" "${THE_ORDER_UPSTREAM_PORT}" false false "https://the-order.sankofa.nexus" && updated_count=$((updated_count + 1)); } || failed_count=$((failed_count + 1))
|
|
# Sankofa Studio (FusionAI) — VMID 7805; UI at /studio/ on same origin (port 8000). Prefer IP_SANKOFA_STUDIO from ip-addresses.conf / .env
|
|
IP_SANKOFA_STUDIO="${IP_SANKOFA_STUDIO:-192.168.11.72}"
|
|
SANKOFA_STUDIO_PORT="${SANKOFA_STUDIO_PORT:-8000}"
|
|
# block_exploits false — studio UI/API may POST; align with portal policy (avoid spurious 405 from NPM WAF)
|
|
update_proxy_host "studio.sankofa.nexus" "http://${IP_SANKOFA_STUDIO}:${SANKOFA_STUDIO_PORT}" false false && updated_count=$((updated_count + 1)) || { add_proxy_host "studio.sankofa.nexus" "${IP_SANKOFA_STUDIO}" "${SANKOFA_STUDIO_PORT}" false 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 ""
|