#!/bin/bash # ===================================================================== # Fix: Guacamole DB schema + NPM data migration # ===================================================================== # Guacamole: The initdb.sh docker run failed due to the AppArmor issue, # so postgres got garbage instead of the schema SQL. This script # wipes the DB volume, re-generates the schema, and restarts clean. # # NPM: SSH to HAOS failed, so no data was migrated. This script pulls # the addon data via the HA Supervisor partial backup API. # # Prerequisites: Run fix-docker-lxc.sh first to fix the AppArmor issue. # Run on Proxmox host (10.0.0.240) as root. # ===================================================================== set -euo pipefail HA_URL="http://10.0.0.55:8123" HA_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJlMDY2YmRhYTc0OGU0Yjg2YmIwNTAyOWRkZmVjOGUwOSIsImlhdCI6MTc3OTg0MjE5NywiZXhwIjoyMDk1MjAyMTk3fQ.xA0UVpgbOxrvtMVZVnI45vhy7IxDhD2vCAT4mgJcYgk" echo "============================================" echo " Fixing Guacamole (CT 121) + NPM (CT 122)" echo "============================================" # ================================================================= # FIX 1: GUACAMOLE # ================================================================= echo "" echo "=== [1/2] Fixing Guacamole (CT 121) ===" echo " Stopping stack and wiping broken DB volume..." pct exec 121 -- bash -c 'cd /opt/guacamole && docker compose down -v' 2>/dev/null || true sleep 3 echo " Regenerating database schema..." pct exec 121 -- bash -c ' rm -f /opt/guacamole/initdb/001-init.sql docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgresql \ > /opt/guacamole/initdb/001-init.sql 2>/dev/null SCHEMA_SIZE=$(wc -c < /opt/guacamole/initdb/001-init.sql) echo " Schema file: ${SCHEMA_SIZE} bytes" if [ "${SCHEMA_SIZE}" -lt 1000 ]; then echo " ERROR: Schema too small, docker run may still be failing" exit 1 fi ' echo " Starting fresh stack..." pct exec 121 -- bash -c 'cd /opt/guacamole && docker compose up -d' echo " Waiting 30s for postgres init..." sleep 30 HTTP_GUAC=$(pct exec 121 -- curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/guacamole/ 2>/dev/null || echo "000") if [ "$HTTP_GUAC" = "200" ] || [ "$HTTP_GUAC" = "302" ]; then echo " Guacamole is UP" else echo " HTTP ${HTTP_GUAC} - checking logs..." pct exec 121 -- docker logs guacamole 2>&1 | tail -15 fi # ================================================================= # FIX 2: NPM DATA MIGRATION # ================================================================= echo "" echo "=== [2/2] Migrating NPM data (CT 122) ===" NPM_MIGRATED=false TMPDIR=$(mktemp -d) # Try SSH first (ports 22222 and 22) for PORT in 22222 22; do if ssh -o ConnectTimeout=3 -o StrictHostKeyChecking=no -p ${PORT} \ root@10.0.0.55 "test -d /addon_data/a0d7b954_nginxproxymanager" 2>/dev/null; then echo " SSH connected (port ${PORT}), copying data..." scp -P ${PORT} -r -o StrictHostKeyChecking=no \ root@10.0.0.55:/addon_data/a0d7b954_nginxproxymanager/ \ "${TMPDIR}/npm_data/" 2>/dev/null NPM_MIGRATED=true break fi done # Try HA Supervisor partial backup if SSH failed if [ "$NPM_MIGRATED" = false ]; then echo " SSH failed. Trying HA Supervisor partial backup..." BACKUP_RESPONSE=$(curl -s -X POST \ -H "Authorization: Bearer ${HA_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"name":"npm-migration","addons":["a0d7b954_nginxproxymanager"],"folders":[]}' \ "${HA_URL}/api/hassio/backups/new/partial" 2>/dev/null) BACKUP_SLUG=$(echo "${BACKUP_RESPONSE}" | python3 -c " import sys,json try: d=json.load(sys.stdin); print(d.get('data',{}).get('slug','')) except: print('') " 2>/dev/null) if [ -n "${BACKUP_SLUG}" ] && [ "${BACKUP_SLUG}" != "" ]; then echo " Backup created (${BACKUP_SLUG}), downloading..." curl -s -o "${TMPDIR}/npm-backup.tar" \ -H "Authorization: Bearer ${HA_TOKEN}" \ "${HA_URL}/api/hassio/backups/${BACKUP_SLUG}/download" 2>/dev/null if [ -f "${TMPDIR}/npm-backup.tar" ] && [ -s "${TMPDIR}/npm-backup.tar" ]; then mkdir -p "${TMPDIR}/npm_data" cd "${TMPDIR}" && tar xf npm-backup.tar 2>/dev/null || true ADDON_TAR=$(find "${TMPDIR}" -name "*nginxproxymanager*" -name "*.tar.gz" 2>/dev/null | head -1) if [ -n "${ADDON_TAR}" ]; then tar xzf "${ADDON_TAR}" -C "${TMPDIR}/npm_data/" 2>/dev/null || true NPM_MIGRATED=true fi fi curl -s -X DELETE -H "Authorization: Bearer ${HA_TOKEN}" \ "${HA_URL}/api/hassio/backups/${BACKUP_SLUG}" 2>/dev/null || true fi fi # Apply migrated data if [ "$NPM_MIGRATED" = true ]; then echo " Applying NPM data..." pct exec 122 -- bash -c 'cd /opt/npm && docker compose down' 2>/dev/null || true sleep 3 DB_FILE=$(find "${TMPDIR}/npm_data" -name "database.sqlite" -type f 2>/dev/null | head -1) [ -n "${DB_FILE}" ] && pct push 122 "${DB_FILE}" /opt/npm/data/database.sqlite && echo " DB migrated" CERT_DIR=$(find "${TMPDIR}/npm_data" -type d -name "letsencrypt" 2>/dev/null | head -1) if [ -n "${CERT_DIR}" ]; then tar -czf "${TMPDIR}/c.tar.gz" -C "${CERT_DIR}" . 2>/dev/null pct push 122 "${TMPDIR}/c.tar.gz" /tmp/c.tar.gz pct exec 122 -- bash -c 'tar xzf /tmp/c.tar.gz -C /opt/npm/letsencrypt/ && rm /tmp/c.tar.gz' echo " Certs migrated" fi pct exec 122 -- bash -c 'cd /opt/npm && docker compose up -d' sleep 10 echo " NPM restarted with migrated data" else echo "" echo " AUTO-MIGRATION FAILED. Manual steps:" echo " 1. HA > Settings > Backups > Create > Partial" echo " Select ONLY 'Nginx Proxy Manager', create it" echo " 2. Download the backup .tar file" echo " 3. Copy to Proxmox: scp backup.tar root@10.0.0.240:/tmp/" echo " 4. Run:" echo " cd /tmp && tar xf *.tar" echo " tar xzf *nginxproxymanager*.tar.gz -C /tmp/npm_extract/" echo " find /tmp/npm_extract -name database.sqlite" echo " pct exec 122 -- bash -c 'cd /opt/npm && docker compose down'" echo " pct push 122 /tmp/npm_extract/.../database.sqlite /opt/npm/data/database.sqlite" echo " pct exec 122 -- bash -c 'cd /opt/npm && docker compose up -d'" fi rm -rf "${TMPDIR}" echo "" echo "============================================" echo " Guacamole: http://10.0.0.225:8080/guacamole/" echo " Login: guacadmin / guacadmin" echo " NPM: http://10.0.0.226:81" [ "$NPM_MIGRATED" = true ] && echo " Login: existing credentials" || echo " Login: admin@example.com / changeme" echo "============================================"