2026-03-02 11:37:34 -08:00
#!/usr/bin/env bash
2026-02-12 15:46:57 -08:00
set -euo pipefail
2026-03-29 13:41:02 -07:00
# Update Sankofa NPMplus proxy hosts (apex + Phoenix API + the-order) via API by numeric host ID.
# Prefer for production: scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh (domain-based; includes portal.sankofa.nexus, admin.sankofa.nexus, dash when IP_SANKOFA_DASH set).
2026-03-27 11:27:09 -07:00
# NPM proxy host IDs below match backup backup-20260325_183932 (3– 6, 7, 59); override with SANKOFA_NPM_ID_* if your DB differs.
2026-03-27 00:30:28 -07:00
2026-02-12 15:46:57 -08:00
SCRIPT_DIR = " $( cd " $( dirname " ${ BASH_SOURCE [0] } " ) " && pwd ) "
PROJECT_ROOT = " $( cd " $SCRIPT_DIR /.. " && pwd ) "
2026-03-27 00:30:28 -07:00
# shellcheck source=/dev/null
2026-02-12 15:46:57 -08:00
source " ${ PROJECT_ROOT } /config/ip-addresses.conf " 2>/dev/null || true
# Load environment variables
if [ -f " $PROJECT_ROOT /.env " ] ; then
2026-03-27 00:30:28 -07:00
set -a
# shellcheck source=/dev/null
source " $PROJECT_ROOT /.env "
set +a
2026-02-12 15:46:57 -08:00
fi
NPM_URL = " ${ NPM_URL :- https : // ${ IP_NPMPLUS } : 81 } "
NPM_EMAIL = " ${ NPM_EMAIL :- nsatoshi2007 @hotmail.com } "
NPM_PASSWORD = " ${ NPM_PASSWORD :- } "
2026-03-27 00:30:28 -07:00
NPM_CURL_MAX_TIME = " ${ NPM_CURL_MAX_TIME :- 180 } "
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 } "
2026-03-29 13:41:02 -07:00
IP_SANKOFA_PUBLIC_WEB = " ${ IP_SANKOFA_PUBLIC_WEB :- $IP_SANKOFA_PORTAL } "
SANKOFA_PUBLIC_WEB_PORT = " ${ SANKOFA_PUBLIC_WEB_PORT :- $SANKOFA_PORTAL_PORT } "
2026-03-27 14:05:37 -07:00
IP_ORDER_HAPROXY = " ${ IP_ORDER_HAPROXY :- 192 .168.11.39 } "
THE_ORDER_UPSTREAM_IP = " ${ THE_ORDER_UPSTREAM_IP :- ${ IP_ORDER_HAPROXY } } "
THE_ORDER_UPSTREAM_PORT = " ${ THE_ORDER_UPSTREAM_PORT :- 80 } "
2026-03-27 00:30:28 -07:00
2026-03-27 11:27:09 -07:00
# NPM proxy host IDs: sankofa=3, www.sankofa=4, phoenix=5, www.phoenix=6; the-order=7, www.the-order=59 (typical; verify in NPM UI)
2026-03-27 00:30:28 -07:00
SANKOFA_NPM_ID_ROOT = " ${ SANKOFA_NPM_ID_ROOT :- 3 } "
SANKOFA_NPM_ID_WWW = " ${ SANKOFA_NPM_ID_WWW :- 4 } "
SANKOFA_NPM_ID_PHOENIX = " ${ SANKOFA_NPM_ID_PHOENIX :- 5 } "
SANKOFA_NPM_ID_WWW_PHOENIX = " ${ SANKOFA_NPM_ID_WWW_PHOENIX :- 6 } "
2026-03-27 11:27:09 -07:00
SANKOFA_NPM_ID_THE_ORDER = " ${ SANKOFA_NPM_ID_THE_ORDER :- 7 } "
SANKOFA_NPM_ID_WWW_THE_ORDER = " ${ SANKOFA_NPM_ID_WWW_THE_ORDER :- 59 } "
2026-02-12 15:46:57 -08:00
2026-03-27 00:30:28 -07:00
# Optional 4th field: canonical HTTPS apex — NPM advanced_config 301 (www → apex). Matches update-npmplus-proxy-hosts-api.sh.
2026-02-12 15:46:57 -08:00
declare -A PROXY_HOSTS = (
2026-03-29 13:41:02 -07:00
[ " $SANKOFA_NPM_ID_ROOT " ] = " sankofa.nexus| ${ IP_SANKOFA_PUBLIC_WEB } | ${ SANKOFA_PUBLIC_WEB_PORT } | "
[ " $SANKOFA_NPM_ID_WWW " ] = " www.sankofa.nexus| ${ IP_SANKOFA_PUBLIC_WEB } | ${ SANKOFA_PUBLIC_WEB_PORT } |https://sankofa.nexus "
2026-03-27 00:30:28 -07:00
[ " $SANKOFA_NPM_ID_PHOENIX " ] = " phoenix.sankofa.nexus| ${ IP_SANKOFA_PHOENIX_API } | ${ SANKOFA_PHOENIX_API_PORT } | "
[ " $SANKOFA_NPM_ID_WWW_PHOENIX " ] = " www.phoenix.sankofa.nexus| ${ IP_SANKOFA_PHOENIX_API } | ${ SANKOFA_PHOENIX_API_PORT } |https://phoenix.sankofa.nexus "
2026-03-27 11:27:09 -07:00
[ " $SANKOFA_NPM_ID_THE_ORDER " ] = " the-order.sankofa.nexus| ${ THE_ORDER_UPSTREAM_IP } | ${ THE_ORDER_UPSTREAM_PORT } | "
[ " $SANKOFA_NPM_ID_WWW_THE_ORDER " ] = " www.the-order.sankofa.nexus| ${ THE_ORDER_UPSTREAM_IP } | ${ THE_ORDER_UPSTREAM_PORT } |https://the-order.sankofa.nexus "
2026-02-12 15:46:57 -08:00
)
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🔄 Updating Sankofa NPMplus Proxy Hosts"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Authenticate
echo "🔐 Authenticating to NPMplus..."
2026-03-27 00:30:28 -07:00
TOKEN_RESPONSE = $( curl -s -k --connect-timeout 15 --max-time " $NPM_CURL_MAX_TIME " -X POST " $NPM_URL /api/tokens " \
2026-02-12 15:46:57 -08:00
-H "Content-Type: application/json" \
-d " {\"identity\":\" $NPM_EMAIL \",\"secret\":\" $NPM_PASSWORD \"} " )
TOKEN = $( echo " $TOKEN_RESPONSE " | jq -r '.token // empty' 2>/dev/null || echo "" )
if [ -z " $TOKEN " ] || [ " $TOKEN " = "null" ] ; then
echo "❌ Authentication failed"
exit 1
fi
echo "✅ Authentication successful"
echo ""
# Function to update proxy host
update_proxy_host( ) {
local host_id = $1
local domain = $2
local target_ip = $3
local target_port = $4
2026-03-27 00:30:28 -07:00
local canonical_https = " ${ 5 :- } "
2026-02-12 15:46:57 -08:00
echo " 📝 Updating Proxy Host $host_id : $domain → $target_ip : $target_port "
# Get current proxy host
2026-03-27 00:30:28 -07:00
CURRENT_HOST = $( curl -s -k --connect-timeout 15 --max-time " $NPM_CURL_MAX_TIME " -X GET " $NPM_URL /api/nginx/proxy-hosts/ $host_id " \
2026-02-12 15:46:57 -08:00
-H " Authorization: Bearer $TOKEN " 2>/dev/null || echo "{}" )
if [ " $( echo " $CURRENT_HOST " | jq -r '.id // empty' ) " = "" ] ; then
echo " ❌ Proxy host $host_id not found "
return 1
fi
2026-03-27 00:30:28 -07:00
# NPMplus rejects full-document PUT (e.g. locations: null) — send only allowed forward fields.
local scheme = "http"
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 " $target_ip " \
--argjson port " $( echo " $target_port " | sed 's/[^0-9]//g' ) " \
--argjson websocket false \
--argjson block_exploits false \
--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) ' )
RESPONSE = $( curl -s -k --connect-timeout 15 --max-time " ${ NPM_CURL_MAX_TIME :- 120 } " -X PUT " $NPM_URL /api/nginx/proxy-hosts/ $host_id " \
2026-02-12 15:46:57 -08:00
-H " Authorization: Bearer $TOKEN " \
-H "Content-Type: application/json" \
-d " $UPDATE_PAYLOAD " )
UPDATED_ID = $( echo " $RESPONSE " | jq -r '.id // empty' 2>/dev/null || echo "" )
if [ -n " $UPDATED_ID " ] && [ " $UPDATED_ID " != "null" ] ; then
echo " ✅ Successfully updated proxy host $host_id "
return 0
else
echo " ❌ Failed to update proxy host $host_id "
echo " $RESPONSE " | jq '.' 2>/dev/null || echo " $RESPONSE "
2026-03-27 00:30:28 -07:00
if echo " $RESPONSE " | jq -e '.error.code == 403' >/dev/null 2>& 1; then
echo " (403 often means NPM user lacks permission to mutate proxy hosts; check UI role or use an admin identity.)"
fi
2026-02-12 15:46:57 -08:00
return 1
fi
}
# Update all proxy hosts
SUCCESS = 0
FAILED = 0
for host_id in " ${ !PROXY_HOSTS[@] } " ; do
2026-03-27 00:30:28 -07:00
IFS = '|' read -r domain target_ip target_port canonical_https _ <<< " ${ PROXY_HOSTS [ $host_id ] } "
2026-02-12 15:46:57 -08:00
2026-03-27 00:30:28 -07:00
if update_proxy_host " $host_id " " $domain " " $target_ip " " $target_port " " $canonical_https " ; then
2026-02-12 15:46:57 -08:00
( ( SUCCESS++) )
else
( ( FAILED++) )
fi
echo ""
done
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📊 Update Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " ✅ Successfully updated: $SUCCESS "
echo " ❌ Failed: $FAILED "
echo ""
if [ $FAILED -eq 0 ] ; then
echo "🎉 All proxy hosts updated successfully!"
exit 0
else
echo "⚠️ Some proxy hosts failed to update"
exit 1
fi