Files
proxmox/scripts/verify/export-npmplus-config.sh
defiQUG fbda1b4beb
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands
- CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround
- CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check
- NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere
- MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates
- LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 15:46:57 -08:00

269 lines
9.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Export NPMplus configuration (proxy hosts and certificates)
# Verifies configuration matches documentation
set -euo pipefail
# Load IP configuration
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
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
EVIDENCE_DIR="$PROJECT_ROOT/docs/04-configuration/verification-evidence"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
log_error() { echo -e "${RED}[✗]${NC} $1"; }
cd "$PROJECT_ROOT"
# Source .env
if [ -f .env ]; then
set +euo pipefail
source .env 2>/dev/null || true
set -euo pipefail
fi
NPM_URL="${NPM_URL:-https://${IP_NPMPLUS}:81}"
NPM_EMAIL="${NPM_EMAIL:-nsatoshi2007@hotmail.com}"
NPM_PASSWORD="${NPM_PASSWORD:-}"
NPMPLUS_VMID="${NPMPLUS_VMID:-${NPM_VMID:-10233}}"
NPMPLUS_HOST="${NPMPLUS_HOST:-${NPM_PROXMOX_HOST:-${PROXMOX_HOST:-192.168.11.11}}}"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTPUT_DIR="$EVIDENCE_DIR/npmplus-verification-$TIMESTAMP"
mkdir -p "$OUTPUT_DIR"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🔍 NPMplus Configuration Verification & Export"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Authenticate to NPMplus
log_info "Authenticating to NPMplus..."
if [ -z "$NPM_PASSWORD" ]; then
log_warn "NPM_PASSWORD not found in .env - skipping NPMplus verification"
log_info "To enable: add NPM_PASSWORD and NPM_EMAIL to .env (see config/ip-addresses.conf)"
log_success "Skipped (optional)"
exit 0
fi
TOKEN_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/tokens" \
-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
ERROR_MSG=$(echo "$TOKEN_RESPONSE" | jq -r '.error.message // "Unknown error"' 2>/dev/null || echo "$TOKEN_RESPONSE")
log_error "Authentication failed: $ERROR_MSG"
exit 1
fi
log_success "Authentication successful"
echo ""
# Verify container status
log_info "Verifying NPMplus container status..."
CONTAINER_STATUS=$(ssh -o StrictHostKeyChecking=no root@"$NPMPLUS_HOST" "pct status $NPMPLUS_VMID 2>/dev/null || echo 'not-found'" 2>/dev/null || echo "unknown")
if echo "$CONTAINER_STATUS" | grep -q "running"; then
log_success "Container VMID $NPMPLUS_VMID is running"
elif echo "$CONTAINER_STATUS" | grep -q "stopped"; then
log_warn "Container VMID $NPMPLUS_VMID is stopped"
else
log_warn "Could not determine container status"
fi
# Get container IP
CONTAINER_IP=$(ssh -o StrictHostKeyChecking=no root@"$NPMPLUS_HOST" "pct config $NPMPLUS_VMID 2>/dev/null | grep -E '^ip[0-9]+' | head -1 | awk -F'=' '{print \$2}' | awk '{print \$1}'" 2>/dev/null || echo "")
if [ -n "$CONTAINER_IP" ]; then
log_info "Container IP: $CONTAINER_IP"
fi
echo ""
# Export proxy hosts
log_info "Exporting proxy hosts..."
PROXY_HOSTS_RESPONSE=$(curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts" \
-H "Authorization: Bearer $TOKEN")
if [ $? -ne 0 ]; then
log_error "Failed to fetch proxy hosts"
exit 1
fi
PROXY_HOSTS=$(echo "$PROXY_HOSTS_RESPONSE" | jq '.' 2>/dev/null || echo "[]")
echo "$PROXY_HOSTS" > "$OUTPUT_DIR/proxy_hosts.json"
PROXY_HOST_COUNT=$(echo "$PROXY_HOSTS" | jq '. | length' 2>/dev/null || echo "0")
log_success "Exported $PROXY_HOST_COUNT proxy hosts"
# Export certificates
log_info "Exporting SSL certificates..."
CERTIFICATES_RESPONSE=$(curl -s -k -X GET "$NPM_URL/api/nginx/certificates" \
-H "Authorization: Bearer $TOKEN")
if [ $? -ne 0 ]; then
log_error "Failed to fetch certificates"
exit 1
fi
CERTIFICATES=$(echo "$CERTIFICATES_RESPONSE" | jq '.' 2>/dev/null || echo "[]")
echo "$CERTIFICATES" > "$OUTPUT_DIR/certificates.json"
CERT_COUNT=$(echo "$CERTIFICATES" | jq '. | length' 2>/dev/null || echo "0")
log_success "Exported $CERT_COUNT certificates"
# Verify certificate files on disk
log_info ""
log_info "Verifying certificate files on disk..."
VERIFIED_CERTS=0
MISSING_CERTS=0
CERT_VERIFICATION=()
while IFS= read -r cert; do
cert_id=$(echo "$cert" | jq -r '.id' 2>/dev/null || echo "")
cert_name=$(echo "$cert" | jq -r '.nice_name // "cert-'$cert_id'"' 2>/dev/null || echo "")
domains=$(echo "$cert" | jq -r '.domain_names | join(", ")' 2>/dev/null || echo "")
if [ -z "$cert_id" ] || [ "$cert_id" = "null" ]; then
continue
fi
# Check certificate files in container
CERT_DIR="/data/tls/certbot/live/npm-$cert_id"
fullchain_exists=$(ssh -o StrictHostKeyChecking=no root@"$NPMPLUS_HOST" \
"pct exec $NPMPLUS_VMID -- test -f $CERT_DIR/fullchain.pem && echo 'yes' || echo 'no'" 2>/dev/null || echo "unknown")
privkey_exists=$(ssh -o StrictHostKeyChecking=no root@"$NPMPLUS_HOST" \
"pct exec $NPMPLUS_VMID -- test -f $CERT_DIR/privkey.pem && echo 'yes' || echo 'no'" 2>/dev/null || echo "unknown")
# Get certificate expiration from file if it exists
expires_from_file=""
if [ "$fullchain_exists" = "yes" ]; then
expires_from_file=$(ssh -o StrictHostKeyChecking=no root@"$NPMPLUS_HOST" \
"pct exec $NPMPLUS_VMID -- openssl x509 -in $CERT_DIR/fullchain.pem -noout -enddate 2>/dev/null | cut -d= -f2" 2>/dev/null || echo "")
fi
if [ "$fullchain_exists" = "yes" ] && [ "$privkey_exists" = "yes" ]; then
VERIFIED_CERTS=$((VERIFIED_CERTS + 1))
log_success "Cert ID $cert_id ($cert_name): Files exist"
if [ -n "$expires_from_file" ]; then
log_info " Expires: $expires_from_file"
fi
else
MISSING_CERTS=$((MISSING_CERTS + 1))
log_warn "Cert ID $cert_id ($cert_name): Files missing"
fi
CERT_VERIFICATION+=("{\"cert_id\":$cert_id,\"cert_name\":\"$cert_name\",\"domains\":\"$domains\",\"fullchain_exists\":\"$fullchain_exists\",\"privkey_exists\":\"$privkey_exists\",\"expires_from_file\":\"$expires_from_file\"}")
done < <(echo "$CERTIFICATES" | jq -c '.[]' 2>/dev/null || true)
# Write certificate verification results
echo "${CERT_VERIFICATION[@]}" | jq -s '.' > "$OUTPUT_DIR/certificate_verification.json"
# Generate report
REPORT_FILE="$OUTPUT_DIR/verification_report.md"
cat > "$REPORT_FILE" <<EOF
# NPMplus Configuration Verification Report
**Date**: $(date -Iseconds)
**NPMplus URL**: $NPM_URL
**Container VMID**: $NPMPLUS_VMID
**Container Host**: $NPMPLUS_HOST
**Verifier**: $(whoami)
## Summary
| Component | Count |
|-----------|-------|
| Proxy Hosts | $PROXY_HOST_COUNT |
| SSL Certificates | $CERT_COUNT |
| Verified Certificate Files | $VERIFIED_CERTS |
| Missing Certificate Files | $MISSING_CERTS |
## Container Status
- **VMID**: $NPMPLUS_VMID
- **Host**: $NPMPLUS_HOST
- **Status**: $CONTAINER_STATUS
- **Container IP**: ${CONTAINER_IP:-unknown}
## Proxy Hosts
Exported $PROXY_HOST_COUNT proxy hosts. See \`proxy_hosts.json\` for complete details.
## SSL Certificates
Exported $CERT_COUNT certificates. Certificate file verification:
EOF
for cert_ver in "${CERT_VERIFICATION[@]}"; do
cert_id=$(echo "$cert_ver" | jq -r '.cert_id' 2>/dev/null || echo "")
cert_name=$(echo "$cert_ver" | jq -r '.cert_name' 2>/dev/null || echo "")
domains=$(echo "$cert_ver" | jq -r '.domains' 2>/dev/null || echo "")
fullchain_exists=$(echo "$cert_ver" | jq -r '.fullchain_exists' 2>/dev/null || echo "")
privkey_exists=$(echo "$cert_ver" | jq -r '.privkey_exists' 2>/dev/null || echo "")
expires=$(echo "$cert_ver" | jq -r '.expires_from_file' 2>/dev/null || echo "")
status_icon="❌"
if [ "$fullchain_exists" = "yes" ] && [ "$privkey_exists" = "yes" ]; then
status_icon="✅"
fi
echo "" >> "$REPORT_FILE"
echo "### Cert ID $cert_id: $cert_name" >> "$REPORT_FILE"
echo "- Domains: $domains" >> "$REPORT_FILE"
echo "- Fullchain: $fullchain_exists $status_icon" >> "$REPORT_FILE"
echo "- Privkey: $privkey_exists $status_icon" >> "$REPORT_FILE"
if [ -n "$expires" ]; then
echo "- Expires: $expires" >> "$REPORT_FILE"
fi
done
cat >> "$REPORT_FILE" <<EOF
## Files Generated
- \`proxy_hosts.json\` - Complete proxy hosts export
- \`certificates.json\` - Complete certificates export
- \`certificate_verification.json\` - Certificate file verification results
- \`verification_report.md\` - This report
## Next Steps
1. Review proxy hosts configuration
2. Verify certificate files match API data
3. Check for any missing certificate files
4. Update source-of-truth JSON after verification
EOF
log_info ""
log_info "Verification complete!"
log_success "Proxy hosts export: $OUTPUT_DIR/proxy_hosts.json"
log_success "Certificates export: $OUTPUT_DIR/certificates.json"
log_success "Report: $REPORT_FILE"
log_info "Summary: $PROXY_HOST_COUNT proxy hosts, $CERT_COUNT certificates, $VERIFIED_CERTS verified cert files"