feat(it-ops): LAN bootstrap for read API, NPM proxy, Cloudflare DNS
All checks were successful
Deploy to Phoenix / deploy (push) Successful in 6s
All checks were successful
Deploy to Phoenix / deploy (push) Successful in 6s
- bootstrap-sankofa-it-read-api-lan.sh: rsync /opt/proxmox, systemd + env file, repo .env keys, portal CT 7801 merge, weekly export timer; tolerate export exit 2 - upsert-it-read-api-proxy-host.sh, add-it-api-sankofa-dns.sh - systemd example uses EnvironmentFile; docs, spec, AGENTS, read API README Made-with: Cursor
This commit is contained in:
85
scripts/nginx-proxy-manager/upsert-it-read-api-proxy-host.sh
Executable file
85
scripts/nginx-proxy-manager/upsert-it-read-api-proxy-host.sh
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
# Upsert NPMplus proxy host for the IT read API (Phase 0).
|
||||
# Point DNS (e.g. it-api.sankofa.nexus) at your NPM public IP before using TLS.
|
||||
#
|
||||
# Env: NPM_URL, NPM_EMAIL, NPM_PASSWORD; optional:
|
||||
# IT_READ_API_PUBLIC_HOST (default it-api.sankofa.nexus)
|
||||
# IT_READ_API_UPSTREAM_IP (default PROXMOX_HOST_R630_01 or 192.168.11.11)
|
||||
# IT_READ_API_UPSTREAM_PORT (default 8787)
|
||||
# NPM_CURL_MAX_TIME (default 300)
|
||||
set -euo pipefail
|
||||
|
||||
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
|
||||
|
||||
_orig_npm_url="${NPM_URL:-}"
|
||||
_orig_npm_email="${NPM_EMAIL:-}"
|
||||
_orig_npm_password="${NPM_PASSWORD:-}"
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then set +u; source "$PROJECT_ROOT/.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"
|
||||
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
||||
|
||||
NPM_URL="${NPM_URL:-https://${IP_NPMPLUS:-192.168.11.167}:81}"
|
||||
NPM_EMAIL="${NPM_EMAIL:-}"
|
||||
NPM_PASSWORD="${NPM_PASSWORD:-}"
|
||||
[ -z "$NPM_PASSWORD" ] && { echo "NPM_PASSWORD required (.env or export)" >&2; exit 1; }
|
||||
|
||||
DOMAIN="${IT_READ_API_PUBLIC_HOST:-it-api.sankofa.nexus}"
|
||||
UP_IP="${IT_READ_API_UPSTREAM_IP:-${PROXMOX_HOST_R630_01:-192.168.11.11}}"
|
||||
UP_PORT="${IT_READ_API_UPSTREAM_PORT:-8787}"
|
||||
|
||||
NPM_CURL_MAX_TIME="${NPM_CURL_MAX_TIME:-300}"
|
||||
curl_npm() { curl -s -k -L --http1.1 --connect-timeout 30 --max-time "$NPM_CURL_MAX_TIME" "$@"; }
|
||||
|
||||
try_connect() { curl -s -k -L -o /dev/null --connect-timeout 5 --max-time 20 "$1" 2>/dev/null; }
|
||||
if ! try_connect "$NPM_URL/"; then
|
||||
http_url="${NPM_URL/https:/http:}"
|
||||
try_connect "$http_url/" && NPM_URL="$http_url"
|
||||
fi
|
||||
|
||||
AUTH_JSON=$(jq -n --arg identity "$NPM_EMAIL" --arg secret "$NPM_PASSWORD" '{identity:$identity,secret:$secret}')
|
||||
TOKEN=$(curl_npm -X POST "$NPM_URL/api/tokens" -H "Content-Type: application/json" -d "$AUTH_JSON" | jq -r '.token // empty')
|
||||
[ -n "$TOKEN" ] && [ "$TOKEN" != "null" ] || { echo "NPM auth failed" >&2; exit 1; }
|
||||
|
||||
ADV='add_header Referrer-Policy "strict-origin-when-cross-origin" always;'
|
||||
PAYLOAD_ADD=$(jq -n \
|
||||
--arg domain "$DOMAIN" \
|
||||
--arg host "$UP_IP" \
|
||||
--argjson port "$UP_PORT" \
|
||||
--arg adv "$ADV" \
|
||||
'{domain_names:[$domain],forward_scheme:"http",forward_host:$host,forward_port:$port,allow_websocket_upgrade:false,block_exploits:true,certificate_id:null,ssl_forced:false,advanced_config:$adv}')
|
||||
|
||||
echo "Trying create (POST) for $DOMAIN -> http://${UP_IP}:${UP_PORT}"
|
||||
RESP=$(curl_npm -X POST "$NPM_URL/api/nginx/proxy-hosts" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "$PAYLOAD_ADD")
|
||||
if echo "$RESP" | jq -e '.id' >/dev/null 2>&1; then
|
||||
echo "OK created id=$(echo "$RESP" | jq -r .id)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ERR_MSG=$(echo "$RESP" | jq -r '.message // .error.message // .error // empty' 2>/dev/null || echo "")
|
||||
if ! echo "$ERR_MSG" | grep -qiE 'already|in use|exist|duplicate|unique'; then
|
||||
echo "Create failed (not a duplicate case): $ERR_MSG" >&2
|
||||
echo "$RESP" | jq . 2>/dev/null || echo "$RESP"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Host exists; fetching proxy list for PUT ($ERR_MSG)"
|
||||
PROXY_JSON=$(curl_npm -X GET "$NPM_URL/api/nginx/proxy-hosts" -H "Authorization: Bearer $TOKEN")
|
||||
HOST_ID=$(echo "$PROXY_JSON" | jq -r --arg d "$DOMAIN" '.[] | select(.domain_names | type == "array") | select(any(.domain_names[]; (. | tostring | ascii_downcase) == ($d | ascii_downcase))) | .id' | head -n1)
|
||||
|
||||
if [ -z "$HOST_ID" ] || [ "$HOST_ID" = "null" ]; then
|
||||
echo "Could not resolve proxy host id for $DOMAIN." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating proxy host $DOMAIN (id=$HOST_ID) -> http://${UP_IP}:${UP_PORT}"
|
||||
PAYLOAD_PUT=$(jq -n \
|
||||
--arg host "$UP_IP" \
|
||||
--argjson port "$UP_PORT" \
|
||||
--arg adv "$ADV" \
|
||||
'{forward_scheme:"http",forward_host:$host,forward_port:$port,allow_websocket_upgrade:false,block_exploits:true,advanced_config:$adv}')
|
||||
RESP=$(curl_npm -X PUT "$NPM_URL/api/nginx/proxy-hosts/$HOST_ID" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "$PAYLOAD_PUT")
|
||||
echo "$RESP" | jq -e '.id' >/dev/null && echo "OK updated" || { echo "$RESP" | jq . 2>/dev/null || echo "$RESP"; exit 1; }
|
||||
Reference in New Issue
Block a user