feat(sankofa): public web CT 7806, portal NPM/DNS defaults, Keycloak redirect helper
- Provision/sync scripts and systemd for corporate Next on 7806; IP_SANKOFA_PUBLIC_WEB for apex NPM - Portal stack: NEXTAUTH_URL default portal.sankofa.nexus; NPM fleet + migrate + DNS ordering - keycloak-sankofa-ensure-client-redirects.sh (KEYCLOAK_ADMIN_PASSWORD); .env.master.example hints - Docs: task list, inventory, FQDN/E2E/EXPECTED_WEB_CONTENT, AGENTS pointers Made-with: Cursor
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Enable working login on https://sankofa.nexus:
|
||||
# Enable working login on the client portal hostname (https://portal.sankofa.nexus; NEXTAUTH_URL):
|
||||
# - Fix Keycloak systemd (JAVA_HOME line; hostname + proxy headers for NPM).
|
||||
# - Remove .env.local on CT 7801; install .env with PORTAL_LOCAL_LOGIN_* + NEXTAUTH_SECRET.
|
||||
# - Run sync-sankofa-portal-7801.sh (rebuild portal with updated auth.ts).
|
||||
@@ -32,7 +32,7 @@ cat > "$ENV_TMP" <<EOF
|
||||
NEXT_PUBLIC_GRAPHQL_ENDPOINT=http://192.168.11.50:4000/graphql
|
||||
NEXT_PUBLIC_GRAPHQL_WS_ENDPOINT=ws://192.168.11.50:4000/graphql-ws
|
||||
|
||||
NEXTAUTH_URL=https://sankofa.nexus
|
||||
NEXTAUTH_URL=https://portal.sankofa.nexus
|
||||
NEXTAUTH_SECRET=${NEXTAUTH_SEC}
|
||||
KEYCLOAK_URL=https://keycloak.sankofa.nexus
|
||||
KEYCLOAK_REALM=master
|
||||
@@ -85,7 +85,7 @@ bash "${SCRIPT_DIR}/sync-sankofa-portal-7801.sh"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "✅ Sign in at https://sankofa.nexus"
|
||||
echo "✅ Sign in at https://portal.sankofa.nexus (NEXTAUTH_URL)"
|
||||
echo " Email: ${LOCAL_EMAIL}"
|
||||
echo " Password: ${GEN_PASS}"
|
||||
echo ""
|
||||
|
||||
101
scripts/deployment/keycloak-sankofa-ensure-client-redirects.sh
Executable file
101
scripts/deployment/keycloak-sankofa-ensure-client-redirects.sh
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env bash
|
||||
# Ensure Keycloak OIDC client has redirect URIs and web origins for portal/admin hostnames.
|
||||
# Uses Admin REST API (password grant on master realm). Set secrets in .env (not committed).
|
||||
#
|
||||
# Required env: KEYCLOAK_ADMIN_PASSWORD
|
||||
# Optional: KEYCLOAK_URL (default https://keycloak.sankofa.nexus), KEYCLOAK_ADMIN (default admin),
|
||||
# KEYCLOAK_REALM (default master), KEYCLOAK_CLIENT_ID (default sankofa-portal)
|
||||
#
|
||||
# Usage: from repo root with .env loaded:
|
||||
# ./scripts/deployment/keycloak-sankofa-ensure-client-redirects.sh
|
||||
# ./scripts/deployment/keycloak-sankofa-ensure-client-redirects.sh --dry-run
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
if [ -f "$PROJECT_ROOT/.env" ]; then
|
||||
set +u
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source "$PROJECT_ROOT/.env" 2>/dev/null || true
|
||||
set +a
|
||||
set -u
|
||||
fi
|
||||
|
||||
KEYCLOAK_URL="${KEYCLOAK_URL:-https://keycloak.sankofa.nexus}"
|
||||
REALM="${KEYCLOAK_REALM:-master}"
|
||||
CLIENT_ID="${KEYCLOAK_CLIENT_ID:-sankofa-portal}"
|
||||
ADMIN_USER="${KEYCLOAK_ADMIN:-admin}"
|
||||
ADMIN_PASS="${KEYCLOAK_ADMIN_PASSWORD:-}"
|
||||
|
||||
DRY=0
|
||||
[[ "${1:-}" == "--dry-run" ]] && DRY=1
|
||||
|
||||
if [ -z "$ADMIN_PASS" ]; then
|
||||
echo "KEYCLOAK_ADMIN_PASSWORD is not set. Add it to .env (or export) and re-run." >&2
|
||||
echo "Without it, update the client manually: Valid redirect URIs + Web origins for portal/admin." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TOKEN_JSON=$(curl -sS -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \
|
||||
-d "grant_type=password" \
|
||||
-d "client_id=admin-cli" \
|
||||
-d "username=${ADMIN_USER}" \
|
||||
-d "password=${ADMIN_PASS}")
|
||||
|
||||
TOKEN=$(echo "$TOKEN_JSON" | jq -r '.access_token // empty')
|
||||
if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
|
||||
echo "Failed to obtain admin token (check URL, user, password)." >&2
|
||||
echo "$TOKEN_JSON" | jq -r '.error_description // .error // .' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CLIENT_LIST=$(curl -sS -G "${KEYCLOAK_URL}/admin/realms/${REALM}/clients" \
|
||||
-H "Authorization: Bearer ${TOKEN}" \
|
||||
--data-urlencode "clientId=${CLIENT_ID}")
|
||||
|
||||
INTERNAL_ID=$(echo "$CLIENT_LIST" | jq -r '.[0].id // empty')
|
||||
if [ -z "$INTERNAL_ID" ] || [ "$INTERNAL_ID" = "null" ]; then
|
||||
echo "No client with clientId=${CLIENT_ID} in realm ${REALM}." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FULL=$(curl -sS "${KEYCLOAK_URL}/admin/realms/${REALM}/clients/${INTERNAL_ID}" \
|
||||
-H "Authorization: Bearer ${TOKEN}")
|
||||
|
||||
DESIRED_REDIRECTS='[
|
||||
"https://portal.sankofa.nexus/*",
|
||||
"https://portal.sankofa.nexus",
|
||||
"https://admin.sankofa.nexus/*",
|
||||
"https://admin.sankofa.nexus"
|
||||
]'
|
||||
DESIRED_ORIGINS='[
|
||||
"https://portal.sankofa.nexus",
|
||||
"https://admin.sankofa.nexus"
|
||||
]'
|
||||
|
||||
MERGED=$(echo "$FULL" | jq --argjson dr "$DESIRED_REDIRECTS" --argjson wo "$DESIRED_ORIGINS" '
|
||||
.redirectUris = ((.redirectUris // []) + $dr | unique) |
|
||||
.webOrigins = ((.webOrigins // []) + $wo | unique)
|
||||
')
|
||||
|
||||
if [ "$DRY" = 1 ]; then
|
||||
echo "[dry-run] Would set client ${CLIENT_ID} (${INTERNAL_ID}) to:"
|
||||
echo "$MERGED" | jq '{clientId, redirectUris, webOrigins}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
HTTP_CODE=$(curl -sS -o /tmp/kc_put_body.txt -w "%{http_code}" -X PUT \
|
||||
"${KEYCLOAK_URL}/admin/realms/${REALM}/clients/${INTERNAL_ID}" \
|
||||
-H "Authorization: Bearer ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$MERGED")
|
||||
|
||||
if [[ "$HTTP_CODE" != "204" && "$HTTP_CODE" != "200" ]]; then
|
||||
echo "PUT client failed HTTP ${HTTP_CODE}" >&2
|
||||
cat /tmp/kc_put_body.txt >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f /tmp/kc_put_body.txt
|
||||
echo "Updated Keycloak client ${CLIENT_ID}: redirect URIs and web origins merged (portal + admin)."
|
||||
89
scripts/deployment/provision-sankofa-public-web-lxc-7806.sh
Executable file
89
scripts/deployment/provision-sankofa-public-web-lxc-7806.sh
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create LXC 7806 (sankofa-public-web) for corporate Next.js at repo root → sankofa.nexus via IP_SANKOFA_PUBLIC_WEB.
|
||||
# Installs Node 20 + pnpm and systemd unit; then run sync-sankofa-public-web-to-ct.sh and NPM fleet update.
|
||||
#
|
||||
# Usage (from repo root, SSH to r630-01):
|
||||
# bash scripts/deployment/provision-sankofa-public-web-lxc-7806.sh [--dry-run]
|
||||
#
|
||||
# Env: PROXMOX_HOST, SANKOFA_PUBLIC_WEB_VMID (7806), IP_SANKOFA_PUBLIC_WEB_CT (default 192.168.11.63)
|
||||
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" 2>/dev/null || true
|
||||
|
||||
PROXMOX_HOST="${PROXMOX_HOST:-${PROXMOX_HOST_R630_01:-192.168.11.11}}"
|
||||
VMID="${SANKOFA_PUBLIC_WEB_VMID:-7806}"
|
||||
IP_CT="${IP_SANKOFA_PUBLIC_WEB_CT:-192.168.11.63}"
|
||||
HOSTNAME_CT="${SANKOFA_PUBLIC_WEB_HOSTNAME:-sankofa-public-web}"
|
||||
TEMPLATE="${TEMPLATE:-local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst}"
|
||||
STORAGE="${STORAGE:-local-lvm}"
|
||||
NETWORK="${NETWORK:-vmbr0}"
|
||||
GATEWAY="${NETWORK_GATEWAY:-192.168.11.1}"
|
||||
SSH_OPTS="-o BatchMode=yes -o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new"
|
||||
SERVICE_FILE="${PROJECT_ROOT}/config/systemd/sankofa-public-web.service"
|
||||
|
||||
DRY_RUN=false
|
||||
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true
|
||||
|
||||
echo "=== Provision Sankofa public web LXC ${VMID} (${IP_CT}) ==="
|
||||
echo "Proxmox: ${PROXMOX_HOST}"
|
||||
|
||||
if [[ ! -f "$SERVICE_FILE" ]]; then
|
||||
echo "ERROR: Missing $SERVICE_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo "[DRY-RUN] Would create CT ${VMID} if missing, install Node/pnpm, install systemd unit"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ssh $SSH_OPTS "root@${PROXMOX_HOST}" "pct list 2>/dev/null | grep -q '^${VMID} '"; then
|
||||
echo "CT ${VMID} already exists — skipping pct create"
|
||||
else
|
||||
echo "Creating CT ${VMID} (${HOSTNAME_CT}) @ ${IP_CT}/24..."
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" bash -s <<EOF
|
||||
set -euo pipefail
|
||||
pct create ${VMID} ${TEMPLATE} \
|
||||
--hostname ${HOSTNAME_CT} \
|
||||
--memory 6144 \
|
||||
--cores 2 \
|
||||
--rootfs ${STORAGE}:32 \
|
||||
--net0 name=eth0,bridge=${NETWORK},ip=${IP_CT}/24,gw=${GATEWAY} \
|
||||
--nameserver ${DNS_PRIMARY:-1.1.1.1} \
|
||||
--description 'Sankofa corporate public web (Next.js root) — sankofa.nexus via NPM IP_SANKOFA_PUBLIC_WEB' \
|
||||
--start 1 \
|
||||
--onboot 1 \
|
||||
--unprivileged 0
|
||||
EOF
|
||||
echo "Waiting for CT to boot..."
|
||||
sleep 20
|
||||
fi
|
||||
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" "pct status ${VMID}" | grep -q running || { echo "ERROR: CT ${VMID} not running"; exit 1; }
|
||||
|
||||
echo "Installing Node 20 + pnpm inside CT ${VMID}..."
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" "pct exec ${VMID} -- bash -lc '
|
||||
set -euo pipefail
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq ca-certificates curl gnupg
|
||||
if ! command -v node >/dev/null 2>&1 || ! node -v | grep -q \"^v20\"; then
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
apt-get install -y -qq nodejs
|
||||
fi
|
||||
command -v pnpm >/dev/null 2>&1 || npm install -g pnpm
|
||||
mkdir -p /opt/sankofa-public-web
|
||||
'"
|
||||
|
||||
echo "Installing systemd unit..."
|
||||
scp $SSH_OPTS "$SERVICE_FILE" "root@${PROXMOX_HOST}:/tmp/sankofa-public-web.service"
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" "pct push ${VMID} /tmp/sankofa-public-web.service /etc/systemd/system/sankofa-public-web.service && rm -f /tmp/sankofa-public-web.service"
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" "pct exec ${VMID} -- systemctl daemon-reload"
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" "pct exec ${VMID} -- systemctl enable sankofa-public-web"
|
||||
|
||||
echo "✅ CT ${VMID} ready. Next:"
|
||||
echo " SANKOFA_PUBLIC_WEB_VMID=${VMID} bash scripts/deployment/sync-sankofa-public-web-to-ct.sh"
|
||||
echo " Then set IP_SANKOFA_PUBLIC_WEB=${IP_CT} and run scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh"
|
||||
@@ -14,7 +14,7 @@ PROXMOX_HOST="${PROXMOX_HOST:-${PROXMOX_HOST_R630_01:-192.168.11.11}}"
|
||||
VMID="${SANKOFA_PORTAL_VMID:-7801}"
|
||||
CT_APP_DIR="${SANKOFA_PORTAL_CT_DIR:-/opt/sankofa-portal}"
|
||||
SERVICE_NAME="${SANKOFA_PORTAL_SERVICE:-sankofa-portal}"
|
||||
NEXTAUTH_PUBLIC_URL="${SANKOFA_PORTAL_NEXTAUTH_URL:-https://sankofa.nexus}"
|
||||
NEXTAUTH_PUBLIC_URL="${SANKOFA_PORTAL_NEXTAUTH_URL:-https://portal.sankofa.nexus}"
|
||||
SSH_OPTS="-o BatchMode=yes -o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new"
|
||||
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" "pct exec ${VMID} -- bash -s" <<EOF
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# ./scripts/deployment/sync-sankofa-portal-7801.sh [--dry-run]
|
||||
# Env:
|
||||
# PROXMOX_HOST (default 192.168.11.11), SANKOFA_PORTAL_VMID (7801), SANKOFA_PORTAL_SRC, IP_SANKOFA_PORTAL (for post-check only)
|
||||
# SANKOFA_PORTAL_NEXTAUTH_URL (default https://sankofa.nexus) — applied on CT after build
|
||||
# SANKOFA_PORTAL_NEXTAUTH_URL (default https://portal.sankofa.nexus) — applied on CT after build
|
||||
#
|
||||
# See: docs/03-deployment/PUBLIC_SECTOR_LIVE_DEPLOYMENT_CHECKLIST.md (Phoenix CT 7801)
|
||||
|
||||
@@ -97,14 +97,14 @@ REMOTE_EOF
|
||||
|
||||
echo ""
|
||||
echo "🔐 Ensuring NextAuth URL/secret on CT (see sankofa-portal-ensure-nextauth-on-ct.sh)…"
|
||||
SANKOFA_PORTAL_NEXTAUTH_URL="${SANKOFA_PORTAL_NEXTAUTH_URL:-https://sankofa.nexus}"
|
||||
SANKOFA_PORTAL_NEXTAUTH_URL="${SANKOFA_PORTAL_NEXTAUTH_URL:-https://portal.sankofa.nexus}"
|
||||
export SANKOFA_PORTAL_VMID SANKOFA_PORTAL_CT_DIR SANKOFA_PORTAL_SERVICE SANKOFA_PORTAL_NEXTAUTH_URL PROXMOX_HOST
|
||||
bash "${SCRIPT_DIR}/sankofa-portal-ensure-nextauth-on-ct.sh"
|
||||
|
||||
echo ""
|
||||
echo "✅ Done. Verify:"
|
||||
echo " curl -sS http://${IP_SANKOFA_PORTAL:-192.168.11.51}:3000/ | head -c 120"
|
||||
echo " curl -sSI https://sankofa.nexus/api/auth/signin | head -n 15"
|
||||
echo " https://sankofa.nexus/ (via NPM)"
|
||||
echo " curl -sSI https://portal.sankofa.nexus/api/auth/signin | head -n 15"
|
||||
echo " https://portal.sankofa.nexus/ (via NPM; corporate apex is sankofa.nexus → IP_SANKOFA_PUBLIC_WEB)"
|
||||
echo ""
|
||||
echo "Override public auth URL: SANKOFA_PORTAL_NEXTAUTH_URL=https://portal.sankofa.nexus $0"
|
||||
echo "Legacy apex auth URL only if needed: SANKOFA_PORTAL_NEXTAUTH_URL=https://sankofa.nexus $0"
|
||||
|
||||
106
scripts/deployment/sync-sankofa-public-web-to-ct.sh
Executable file
106
scripts/deployment/sync-sankofa-public-web-to-ct.sh
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env bash
|
||||
# Sync Sankofa repo-root Next.js app (corporate / marketing site) to a dedicated LXC for apex sankofa.nexus.
|
||||
# Does not run NextAuth portal setup — use sync-sankofa-portal-7801.sh for client SSO on portal.sankofa.nexus.
|
||||
#
|
||||
# Prerequisites: SSH root@PROXMOX_HOST; sibling repo at ../Sankofa (root package.json + src/app + public/).
|
||||
# On the CT: install systemd unit config/systemd/sankofa-public-web.service → /etc/systemd/system/ and enable.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/deployment/sync-sankofa-public-web-to-ct.sh [--dry-run]
|
||||
# Env:
|
||||
# PROXMOX_HOST, SANKOFA_PUBLIC_WEB_VMID (default 7806), SANKOFA_PUBLIC_WEB_SRC, SANKOFA_PUBLIC_WEB_CT_DIR, SANKOFA_PUBLIC_WEB_SERVICE
|
||||
#
|
||||
# After first deploy: set IP_SANKOFA_PUBLIC_WEB + SANKOFA_PUBLIC_WEB_PORT in config/ip-addresses.conf (or .env) and run
|
||||
# scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh
|
||||
|
||||
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" 2>/dev/null || true
|
||||
|
||||
PROXMOX_HOST="${PROXMOX_HOST:-${PROXMOX_HOST_R630_01:-192.168.11.11}}"
|
||||
VMID="${SANKOFA_PUBLIC_WEB_VMID:-7806}"
|
||||
CT_APP_DIR="${SANKOFA_PUBLIC_WEB_CT_DIR:-/opt/sankofa-public-web}"
|
||||
SERVICE_NAME="${SANKOFA_PUBLIC_WEB_SERVICE:-sankofa-public-web}"
|
||||
SSH_OPTS="-o BatchMode=yes -o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new"
|
||||
|
||||
DEFAULT_SRC="${PROJECT_ROOT}/../Sankofa"
|
||||
if [[ -d "$DEFAULT_SRC" && -f "$DEFAULT_SRC/package.json" ]]; then
|
||||
SANKOFA_PUBLIC_WEB_SRC="${SANKOFA_PUBLIC_WEB_SRC:-$DEFAULT_SRC}"
|
||||
else
|
||||
SANKOFA_PUBLIC_WEB_SRC="${SANKOFA_PUBLIC_WEB_SRC:-}"
|
||||
fi
|
||||
|
||||
DRY_RUN=false
|
||||
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true
|
||||
|
||||
echo "=== Sync Sankofa public (repo root) → CT ${VMID} (${CT_APP_DIR}) ==="
|
||||
echo "Proxmox: ${PROXMOX_HOST}"
|
||||
echo "Source: ${SANKOFA_PUBLIC_WEB_SRC:-<unset>}"
|
||||
echo ""
|
||||
|
||||
if [[ -z "$SANKOFA_PUBLIC_WEB_SRC" || ! -d "$SANKOFA_PUBLIC_WEB_SRC" ]]; then
|
||||
echo "ERROR: Set SANKOFA_PUBLIC_WEB_SRC to the Sankofa monorepo root (parent of portal/)."
|
||||
echo "Example: SANKOFA_PUBLIC_WEB_SRC=/path/to/Sankofa $0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v tar >/dev/null; then
|
||||
echo "ERROR: tar required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TMP_TGZ="${TMPDIR:-/tmp}/sankofa-public-web-sync-$$.tgz"
|
||||
REMOTE_TGZ="/tmp/sankofa-public-web-sync-$$.tgz"
|
||||
CT_TGZ="/tmp/sankofa-public-web-sync.tgz"
|
||||
|
||||
cleanup() { rm -f "$TMP_TGZ"; }
|
||||
trap cleanup EXIT
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo "[DRY-RUN] tar (exclude node_modules,.next,.git) → $TMP_TGZ"
|
||||
echo "[DRY-RUN] scp → root@${PROXMOX_HOST}:${REMOTE_TGZ}"
|
||||
echo "[DRY-RUN] pct push ${VMID} … && systemctl stop ${SERVICE_NAME}"
|
||||
echo "[DRY-RUN] pnpm install && pnpm build && systemctl start ${SERVICE_NAME}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "📦 Archiving Sankofa repo root (excluding node_modules, .next, .git, .env / .env.local)…"
|
||||
tar czf "$TMP_TGZ" \
|
||||
--exclude=node_modules \
|
||||
--exclude=.next \
|
||||
--exclude=portal/node_modules \
|
||||
--exclude=portal/.next \
|
||||
--exclude=.git \
|
||||
--exclude=.env.local \
|
||||
--exclude=.env \
|
||||
-C "$SANKOFA_PUBLIC_WEB_SRC" .
|
||||
|
||||
echo "📤 Copy to Proxmox host…"
|
||||
scp $SSH_OPTS "$TMP_TGZ" "root@${PROXMOX_HOST}:${REMOTE_TGZ}"
|
||||
|
||||
echo "📥 Push into CT ${VMID} and build…"
|
||||
ssh $SSH_OPTS "root@${PROXMOX_HOST}" bash -s <<REMOTE_EOF
|
||||
set -euo pipefail
|
||||
pct push ${VMID} ${REMOTE_TGZ} ${CT_TGZ}
|
||||
rm -f ${REMOTE_TGZ}
|
||||
pct exec ${VMID} -- systemctl stop ${SERVICE_NAME} || true
|
||||
pct exec ${VMID} -- bash -lc 'set -euo pipefail
|
||||
mkdir -p ${CT_APP_DIR}
|
||||
cd ${CT_APP_DIR}
|
||||
tar xzf ${CT_TGZ}
|
||||
rm -f ${CT_TGZ}
|
||||
command -v pnpm >/dev/null || { echo "ERROR: pnpm missing in CT"; exit 1; }
|
||||
pnpm install
|
||||
pnpm build
|
||||
'
|
||||
pct exec ${VMID} -- systemctl start ${SERVICE_NAME}
|
||||
pct exec ${VMID} -- systemctl is-active ${SERVICE_NAME}
|
||||
REMOTE_EOF
|
||||
|
||||
echo ""
|
||||
echo "✅ Done. Point NPM apex with IP_SANKOFA_PUBLIC_WEB / SANKOFA_PUBLIC_WEB_PORT, then:"
|
||||
echo " bash scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh"
|
||||
echo " curl -sS http://${IP_SANKOFA_PUBLIC_WEB:-<CT_IP>}:${SANKOFA_PUBLIC_WEB_PORT:-3000}/ | head -c 120"
|
||||
Reference in New Issue
Block a user