feat(order): HAProxy on 10210, NPM → 192.168.11.39:80

- Add order-haproxy config template and provision-order-haproxy-10210.sh (SSH to r630-01)
- Document one-time unprivileged CT idmap chown repair when apt fails
- Default THE_ORDER_UPSTREAM_* to IP_ORDER_HAPROXY:80; portal bypass via env
- Align update-sankofa-npmplus-proxy-hosts.sh, AGENTS, ALL_VMIDS, E2E notes

Made-with: Cursor
This commit is contained in:
defiQUG
2026-03-27 14:05:37 -07:00
parent 0df175d9cb
commit 430431f2f6
7 changed files with 116 additions and 10 deletions

View File

@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# Install HAProxy in LXC 10210 (order-haproxy) and proxy :80 → Sankofa/Order portal (Next.js).
# Requires SSH to Proxmox host that runs CT 10210 (default: r630-01). See config/ip-addresses.conf.
# Usage: ./scripts/deployment/provision-order-haproxy-10210.sh [--dry-run]
#
# One-time repair (unprivileged CT with host uid 0 on disk → "nobody" inside, apt broken): on Proxmox host,
# pct stop 10210 && pct mount 10210 && chown -R 100000:100000 /var/lib/lxc/10210/rootfs && pct unmount 10210 && pct start 10210
# (Default Proxmox idmap: container root = 100000 on host.)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# shellcheck source=/dev/null
source "$PROJECT_ROOT/config/ip-addresses.conf"
DRY_RUN=false
for a in "$@"; do [[ "$a" == "--dry-run" ]] && DRY_RUN=true; done
PROXMOX="${PROXMOX_ORDER_HAPROXY_NODE:-${PROXMOX_HOST_R630_01:-192.168.11.11}}"
VMID="${ORDER_HAPROXY_VMID:-10210}"
BACKEND_HOST="${ORDER_HAPROXY_BACKEND_HOST:-${IP_SANKOFA_PORTAL:-192.168.11.51}}"
BACKEND_PORT="${ORDER_HAPROXY_BACKEND_PORT:-${SANKOFA_PORTAL_PORT:-3000}}"
TEMPLATE="$PROJECT_ROOT/config/haproxy/order-haproxy-10210.cfg.template"
if [[ ! -r "$TEMPLATE" ]]; then
echo "❌ Missing template: $TEMPLATE"
exit 1
fi
CFG=$(sed -e "s/__BACKEND_HOST__/${BACKEND_HOST}/g" -e "s/__BACKEND_PORT__/${BACKEND_PORT}/g" "$TEMPLATE")
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Provision order-haproxy (CT $VMID on $PROXMOX)"
echo " Backend: http://${BACKEND_HOST}:${BACKEND_PORT}"
echo " Dry-run: $DRY_RUN"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [[ "$DRY_RUN" == true ]]; then
echo "$CFG"
exit 0
fi
remote_run() {
ssh -o BatchMode=yes -o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new \
"${PROXMOX_SSH_USER:-root}@$PROXMOX" "$@"
}
if ! remote_run "pct status $VMID" 2>/dev/null | grep -q running; then
echo "❌ CT $VMID is not running on $PROXMOX"
exit 1
fi
remote_run "pct exec $VMID -- bash -c '
set -e
export DEBIAN_FRONTEND=noninteractive
if ! dpkg -s haproxy >/dev/null 2>&1; then
apt-get update -qq
apt-get install -y -qq haproxy
fi
'"
echo "$CFG" | remote_run "pct exec $VMID -- bash -c 'cat > /etc/haproxy/haproxy.cfg'"
remote_run "pct exec $VMID -- bash -c '
set -e
haproxy -c -f /etc/haproxy/haproxy.cfg
systemctl enable haproxy
systemctl restart haproxy
sleep 1
systemctl is-active --quiet haproxy
echo OK: haproxy active
command -v ss >/dev/null && ss -lntp | grep -E \":80|:443\" || true
'"
IP_ORDER="${IP_ORDER_HAPROXY:-192.168.11.39}"
echo ""
echo "✅ Done. From LAN: curl -sS -o /dev/null -w '%{http_code}\\n' http://${IP_ORDER}:80/"
echo " Then NPM: THE_ORDER_UPSTREAM_IP=${IP_ORDER} THE_ORDER_UPSTREAM_PORT=80 bash scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh"

View File

@@ -389,12 +389,12 @@ 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.
# Default upstream: VMID 10210 order-haproxy @ IP_ORDER_HAPROXY:80 (provision: scripts/deployment/provision-order-haproxy-10210.sh).
# If 10210 is down: THE_ORDER_UPSTREAM_IP=${IP_SANKOFA_PORTAL} THE_ORDER_UPSTREAM_PORT=${SANKOFA_PORTAL_PORT} (direct portal 7801).
# 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}}"
THE_ORDER_UPSTREAM_IP="${THE_ORDER_UPSTREAM_IP:-${IP_ORDER_HAPROXY}}"
THE_ORDER_UPSTREAM_PORT="${THE_ORDER_UPSTREAM_PORT:-80}"
# 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))

View File

@@ -27,8 +27,9 @@ 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}"
THE_ORDER_UPSTREAM_IP="${THE_ORDER_UPSTREAM_IP:-${IP_SANKOFA_PORTAL}}"
THE_ORDER_UPSTREAM_PORT="${THE_ORDER_UPSTREAM_PORT:-${SANKOFA_PORTAL_PORT}}"
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}"
# 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)
SANKOFA_NPM_ID_ROOT="${SANKOFA_NPM_ID_ROOT:-3}"