fix: restore script
This commit is contained in:
@@ -14,10 +14,24 @@
|
|||||||
# - Applies all known post-restore fixes per app
|
# - Applies all known post-restore fixes per app
|
||||||
# - Detects target IP automatically or uses provided one
|
# - Detects target IP automatically or uses provided one
|
||||||
# - Works whether run locally or proxied over SSH
|
# - Works whether run locally or proxied over SSH
|
||||||
|
# - Works inside Docker containers (no ip command needed)
|
||||||
|
# - Supports both docker-compose and docker compose
|
||||||
# =============================================
|
# =============================================
|
||||||
|
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
|
# --------------------------------------------------
|
||||||
|
# Compatibility fixes — must come first
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
# docker compose v2 compat (fixes "docker-compose: command not found")
|
||||||
|
if ! command -v docker-compose &>/dev/null; then
|
||||||
|
if docker compose version &>/dev/null 2>&1; then
|
||||||
|
docker-compose() { docker compose "$@"; }
|
||||||
|
export -f docker-compose
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
@@ -63,11 +77,9 @@ if [ "$REMOTE_MODE" = true ]; then
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
REMOTE_DEST="/tmp/restore-session-$(date +%s)"
|
REMOTE_DEST="/tmp/restore-session-$(date +%s)"
|
||||||
|
|
||||||
# Build SSH/SCP options
|
|
||||||
SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=15"
|
SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=15"
|
||||||
if [ -n "$SSH_KEY" ]; then
|
if [ -n "$SSH_KEY" ]; then
|
||||||
SSH_OPTS="$SSH_OPTS -i $SSH_KEY"
|
SSH_OPTS="$SSH_OPTS -i $SSH_KEY"
|
||||||
SCP_OPTS="$SSH_OPTS"
|
|
||||||
elif [ "$USE_PASSWORD" = true ]; then
|
elif [ "$USE_PASSWORD" = true ]; then
|
||||||
if ! command -v sshpass &>/dev/null; then
|
if ! command -v sshpass &>/dev/null; then
|
||||||
echo "❌ sshpass not installed. Install it with: apt install sshpass"
|
echo "❌ sshpass not installed. Install it with: apt install sshpass"
|
||||||
@@ -123,8 +135,31 @@ fi
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
# Detect IP of this machine
|
# --------------------------------------------------
|
||||||
VM_IP=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v 127.0.0.1 | head -1)
|
# Detect IP — works inside containers too
|
||||||
|
# --------------------------------------------------
|
||||||
|
VM_IP=""
|
||||||
|
|
||||||
|
# Try hostname -I first (works inside containers)
|
||||||
|
if command -v hostname &>/dev/null; then
|
||||||
|
VM_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback: try ip command
|
||||||
|
if [ -z "$VM_IP" ] && command -v ip &>/dev/null; then
|
||||||
|
VM_IP=$(ip -4 addr show 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v 127.0.0.1 | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback: try /proc/net/fib_trie (works in minimal containers)
|
||||||
|
if [ -z "$VM_IP" ] && [ -f /proc/net/fib_trie ]; then
|
||||||
|
VM_IP=$(awk '/32 HOST/{print f} {f=$2}' /proc/net/fib_trie 2>/dev/null | grep -v 127.0.0.1 | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Final fallback: use known main server IP
|
||||||
|
if [ -z "$VM_IP" ]; then
|
||||||
|
VM_IP="173.249.20.244"
|
||||||
|
echo " ⚠️ Could not detect IP, defaulting to $VM_IP"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "========================================="
|
echo "========================================="
|
||||||
echo "🔄 Smart Restore — LOCAL MODE"
|
echo "🔄 Smart Restore — LOCAL MODE"
|
||||||
@@ -165,14 +200,15 @@ declare -A VOLUME_OWNERS=(
|
|||||||
["mautic-setup_mautic-data"]="mautic-app"
|
["mautic-setup_mautic-data"]="mautic-app"
|
||||||
["mautic-setup_mautic-db-data"]="mautic-mariadb"
|
["mautic-setup_mautic-db-data"]="mautic-mariadb"
|
||||||
["n8n-setup_n8n-data"]="n8n-app"
|
["n8n-setup_n8n-data"]="n8n-app"
|
||||||
["n8n-setup_n8n-db-data"]="n8n-db"
|
["n8n-setup_n8n-db-data"]="n8n-postgres"
|
||||||
["odoo-clean_db-data"]="odoo-clean-db-1"
|
["odoo-clean_db-data"]="odoo-clean-db-1"
|
||||||
["odoo-clean_odoo-etc"]="odoo-clean-odoo-1"
|
["odoo-clean_odoo-etc"]="odoo-clean-odoo-1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if [ -d "$SCRIPT_DIR/volumes" ]; then
|
||||||
cd "$SCRIPT_DIR/volumes"
|
cd "$SCRIPT_DIR/volumes"
|
||||||
for backup in *.tar.gz; do
|
for backup in *.tar.gz; do
|
||||||
[ -f "$backup" ] || continue
|
[ -f "$backup" ] || { echo " ⚠️ No volume backups found in $SCRIPT_DIR/volumes"; break; }
|
||||||
volume=$(basename "$backup" .tar.gz)
|
volume=$(basename "$backup" .tar.gz)
|
||||||
owner="${VOLUME_OWNERS[$volume]:-}"
|
owner="${VOLUME_OWNERS[$volume]:-}"
|
||||||
|
|
||||||
@@ -186,12 +222,15 @@ for backup in *.tar.gz; do
|
|||||||
docker volume create "$volume" &>/dev/null || true
|
docker volume create "$volume" &>/dev/null || true
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
-v "${volume}:/target" \
|
-v "${volume}:/target" \
|
||||||
-v "$(pwd):/backup" \
|
-v "$(pwd):/backup:ro" \
|
||||||
alpine \
|
alpine \
|
||||||
sh -c "cd /target && tar xzf /backup/$backup" \
|
sh -c "cd /target && tar xzf /backup/${backup}" \
|
||||||
&& echo "✅" || echo "⚠️ FAILED"
|
&& echo "✅" || echo "⚠️ FAILED"
|
||||||
done
|
done
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No volumes/ directory found in backup — skipping volume restore"
|
||||||
|
fi
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# 2. Start containers — skip healthy ones
|
# 2. Start containers — skip healthy ones
|
||||||
@@ -217,6 +256,7 @@ declare -A APP_MAIN_CONTAINER=(
|
|||||||
["n8n"]="n8n-app"
|
["n8n"]="n8n-app"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if [ -d "$SCRIPT_DIR/compose-files" ]; then
|
||||||
cd "$SCRIPT_DIR/compose-files"
|
cd "$SCRIPT_DIR/compose-files"
|
||||||
for app in Frappe Odoo Nextcloud Mautic n8n; do
|
for app in Frappe Odoo Nextcloud Mautic n8n; do
|
||||||
dir="${APP_DIRS[$app]}"
|
dir="${APP_DIRS[$app]}"
|
||||||
@@ -230,13 +270,16 @@ for app in Frappe Odoo Nextcloud Mautic n8n; do
|
|||||||
if [ -d "$dir" ]; then
|
if [ -d "$dir" ]; then
|
||||||
echo " 🚀 Starting $app..."
|
echo " 🚀 Starting $app..."
|
||||||
cd "$dir"
|
cd "$dir"
|
||||||
docker-compose up -d 2>&1 | tail -3
|
docker compose up -d 2>&1 | tail -3
|
||||||
cd ..
|
cd ..
|
||||||
else
|
else
|
||||||
echo " ⏭️ $app compose dir '$dir' not found, skipping"
|
echo " ⏭️ $app compose dir '$dir' not found, skipping"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No compose-files/ directory found — skipping container start"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "⏳ Waiting 60s for containers to initialize..."
|
echo "⏳ Waiting 60s for containers to initialize..."
|
||||||
@@ -381,16 +424,49 @@ fi
|
|||||||
|
|
||||||
# ---- N8N ----
|
# ---- N8N ----
|
||||||
echo ""
|
echo ""
|
||||||
echo "📌 n8n — Network check..."
|
echo "📌 n8n — Network + volumes check..."
|
||||||
if container_is_healthy n8n-app; then
|
if container_is_healthy n8n-app; then
|
||||||
echo " ⏭️ n8n is healthy, skipping fix"
|
echo " ⏭️ n8n is healthy, skipping fix"
|
||||||
else
|
else
|
||||||
|
# Ensure network exists
|
||||||
docker network inspect integration-network &>/dev/null \
|
docker network inspect integration-network &>/dev/null \
|
||||||
|| docker network create integration-network && echo " ✅ Created integration-network"
|
|| { docker network create integration-network && echo " ✅ Created integration-network"; }
|
||||||
|
|
||||||
if ! docker ps | grep -q n8n-app; then
|
# Check if n8n volumes exist in backup — restore them if not already done
|
||||||
cd "$SCRIPT_DIR/compose-files/n8n-setup" && docker-compose up -d && cd "$SCRIPT_DIR"
|
N8N_VOLUMES=("n8n-setup_n8n-data" "n8n-setup_n8n-db-data")
|
||||||
|
for vol in "${N8N_VOLUMES[@]}"; do
|
||||||
|
vol_backup="$SCRIPT_DIR/volumes/${vol}.tar.gz"
|
||||||
|
if [ -f "$vol_backup" ]; then
|
||||||
|
echo -n " 📁 Restoring $vol ... "
|
||||||
|
docker volume create "$vol" &>/dev/null || true
|
||||||
|
docker run --rm \
|
||||||
|
-v "${vol}:/target" \
|
||||||
|
-v "$SCRIPT_DIR/volumes:/backup:ro" \
|
||||||
|
alpine \
|
||||||
|
sh -c "cd /target && tar xzf /backup/${vol}.tar.gz" \
|
||||||
|
&& echo "✅" || echo "⚠️ FAILED"
|
||||||
|
else
|
||||||
|
echo " ⚠️ $vol backup not found in this archive — n8n will start fresh"
|
||||||
|
docker volume create "$vol" &>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Start n8n via compose if compose file exists
|
||||||
|
N8N_COMPOSE_DIR="$SCRIPT_DIR/compose-files/n8n-setup"
|
||||||
|
if [ -d "$N8N_COMPOSE_DIR" ]; then
|
||||||
|
cd "$N8N_COMPOSE_DIR"
|
||||||
|
docker compose up -d 2>&1 | tail -3
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
else
|
||||||
|
# Fallback: check if n8n-app container exists but is stopped
|
||||||
|
if docker ps -a | grep -q n8n-app; then
|
||||||
|
docker start n8n-app && echo " ✅ Started existing n8n-app container"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No compose file and no existing n8n-app container found"
|
||||||
|
echo " ℹ️ Start manually: docker start n8n-app"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
echo " ✅ n8n → http://${VM_IP}:5678"
|
echo " ✅ n8n → http://${VM_IP}:5678"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user