#!/usr/bin/env bash # Export primary NPMplus configuration for HA setup 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)" if [ -f "$PROJECT_ROOT/.env" ]; then set +euo pipefail source "$PROJECT_ROOT/.env" 2>/dev/null || true set -euo pipefail fi PRIMARY_HOST="${PRIMARY_HOST:-192.168.11.11}" PRIMARY_VMID="${PRIMARY_VMID:-10233}" NPM_URL="${NPM_URL:-https://${IP_NPMPLUS_ETH0:-${IP_NPMPLUS_ETH0:-192.168.11.166}}:81}" NPM_EMAIL="${NPM_EMAIL:-nsatoshi2007@hotmail.com}" NPM_PASSWORD="${NPM_PASSWORD:-}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' 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"; } TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_DIR="/tmp/npmplus-config-backup-$TIMESTAMP" mkdir -p "$BACKUP_DIR" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "📤 Export Primary NPMplus Configuration" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" log_info "Export directory: $BACKUP_DIR" # 1. Export database (copy file directly since sqlite3 may not be available) log_info "Exporting NPMplus database..." # Try sqlite3 dump first, fallback to direct file copy DB_DUMP=$(ssh -o StrictHostKeyChecking=no root@"$PRIMARY_HOST" \ "pct exec $PRIMARY_VMID -- docker exec npmplus sqlite3 /data/database.sqlite '.dump' 2>&1" || echo "") if [ -n "$DB_DUMP" ] && ! echo "$DB_DUMP" | grep -q "executable file not found"; then echo "$DB_DUMP" > "$BACKUP_DIR/database.sql" DB_SIZE=$(stat -f%z "$BACKUP_DIR/database.sql" 2>/dev/null || stat -c%s "$BACKUP_DIR/database.sql" 2>/dev/null || echo "0") if [ "$DB_SIZE" -gt 100 ]; then log_success "Database exported via sqlite3: $BACKUP_DIR/database.sql ($DB_SIZE bytes)" else log_warn "Database dump is very small ($DB_SIZE bytes), trying direct file copy..." # Fall through to direct copy fi fi # Fallback: Copy database file directly if [ ! -f "$BACKUP_DIR/database.sqlite" ]; then log_info "Copying database file directly..." # Copy from container to Proxmox host temp, then to local ssh -o StrictHostKeyChecking=no root@"$PRIMARY_HOST" \ "pct exec $PRIMARY_VMID -- docker cp npmplus:/data/database.sqlite /tmp/db-export.sqlite 2>&1" && \ scp -o StrictHostKeyChecking=no root@"$PRIMARY_HOST:/tmp/db-export.sqlite" \ "$BACKUP_DIR/database.sqlite" 2>&1 && \ ssh -o StrictHostKeyChecking=no root@"$PRIMARY_HOST" "rm -f /tmp/db-export.sqlite" 2>&1 if [ -f "$BACKUP_DIR/database.sqlite" ]; then DB_FILE_SIZE=$(stat -f%z "$BACKUP_DIR/database.sqlite" 2>/dev/null || stat -c%s "$BACKUP_DIR/database.sqlite" 2>/dev/null || echo "0") if [ "$DB_FILE_SIZE" -gt 0 ]; then log_success "Database file copied: $BACKUP_DIR/database.sqlite ($DB_FILE_SIZE bytes)" else log_warn "Database file is empty (0 bytes) - may be uninitialized" # Keep the file anyway for reference fi else log_warn "Database file copy failed - database may be empty or inaccessible" fi fi # 2. Export proxy hosts and certificates via API if [ -n "$NPM_PASSWORD" ]; then log_info "Exporting proxy hosts and certificates via API..." TOKEN_RESPONSE=$(curl -s -k -X POST "$NPM_URL/api/tokens" \ -H "Content-Type: application/json" \ -d "{\"identity\":\"$NPM_EMAIL\",\"secret\":\"$NPM_PASSWORD\"}" 2>/dev/null || echo "{}") TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.token // empty' 2>/dev/null || echo "") if [ -n "$TOKEN" ] && [ "$TOKEN" != "null" ]; then # Export proxy hosts PROXY_HOSTS_JSON=$(curl -s -k -X GET "$NPM_URL/api/nginx/proxy-hosts" \ -H "Authorization: Bearer $TOKEN" 2>/dev/null || echo "[]") echo "$PROXY_HOSTS_JSON" | jq '.' > "$BACKUP_DIR/proxy_hosts.json" 2>/dev/null || echo "[]" > "$BACKUP_DIR/proxy_hosts.json" PROXY_COUNT=$(echo "$PROXY_HOSTS_JSON" | jq '. | length' 2>/dev/null || echo "0") log_success "Proxy hosts exported: $PROXY_COUNT hosts" # Export certificates CERTIFICATES_JSON=$(curl -s -k -X GET "$NPM_URL/api/nginx/certificates" \ -H "Authorization: Bearer $TOKEN" 2>/dev/null || echo "[]") echo "$CERTIFICATES_JSON" | jq '.' > "$BACKUP_DIR/certificates.json" 2>/dev/null || echo "[]" > "$BACKUP_DIR/certificates.json" CERT_COUNT=$(echo "$CERTIFICATES_JSON" | jq '. | length' 2>/dev/null || echo "0") log_success "Certificates metadata exported: $CERT_COUNT certificates" else ERROR_MSG=$(echo "$TOKEN_RESPONSE" | jq -r '.error.message // "Unknown error"' 2>/dev/null || echo "$TOKEN_RESPONSE") log_error "API authentication failed: $ERROR_MSG" log_warn "Continuing with database export only..." fi else log_warn "NPM_PASSWORD not set, skipping API export" log_warn "Only database will be exported" fi # Create summary cat > "$BACKUP_DIR/export-summary.txt" <