rewrited backup script

This commit is contained in:
Dejan R. 2025-11-27 16:29:29 +00:00
parent 6b61177fa1
commit 73e445b7e6

View file

@ -1,134 +1,236 @@
#!/bin/bash
set -e
# ============================================
# CONFIG
# ============================================
BASE_DIR="/home/Dejan/Docker/Netbird-compose"
BACKUP_DIR="${BASE_DIR}/backup"
# Netbird Docker Compose Restore Script
# This script restores a backup and recreates the full directory structure
cd "$BASE_DIR"
# Configuration
COMPOSE_DIR="/home/Dejan/Docker/Netbird-compose"
BACKUP_DIR="${COMPOSE_DIR}/backup"
# ============================================
# SELECT BACKUP FILE
# ============================================
if [[ -n "$1" ]]; then
BACKUP_FILE="$1"
# If a relative path is passed, prepend BACKUP_DIR if file not found
if [[ ! -f "$BACKUP_FILE" ]]; then
if [[ -f "${BACKUP_DIR}/$BACKUP_FILE" ]]; then
BACKUP_FILE="${BACKUP_DIR}/$BACKUP_FILE"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored messages
print_msg() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_question() {
echo -e "${BLUE}[QUESTION]${NC} $1"
}
# Function to show usage
show_usage() {
echo "Usage: $0 <backup-file>"
echo ""
echo "Examples:"
echo " $0 netbird-backup-20241127_161245.tar.gz"
echo " $0 backup/netbird-backup-20241127_161245.tar.gz"
echo " $0 /home/Dejan/Docker/Netbird-compose/backup/netbird-backup-20241127_161245.tar.gz"
echo ""
echo "Available backups:"
if [ -d "$BACKUP_DIR" ]; then
ls -1t "$BACKUP_DIR"/netbird-backup-*.tar.gz 2>/dev/null | head -n 10
else
echo " No backup directory found"
fi
fi
else
# Auto-select latest backup
BACKUP_FILE=$(ls -1t "${BACKUP_DIR}"/netbird_backup_*.tar.gz 2>/dev/null | head -n 1 || true)
fi
exit 1
}
if [[ -z "$BACKUP_FILE" || ! -f "$BACKUP_FILE" ]]; then
echo "ERROR: Backup file not found."
echo "Usage: $0 [path/to/netbird_backup_*.tar.gz]"
# Check if running as root
if [ "$EUID" -ne 0 ]; then
print_error "Please run as root"
exit 1
fi
echo "[*] Using backup file: $BACKUP_FILE"
# Check if backup file argument is provided
if [ -z "$1" ]; then
print_error "No backup file specified"
show_usage
fi
# ============================================
# PREPARE TEMP DIR
# ============================================
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
TEMP_DIR="/tmp/netbird_restore_${TIMESTAMP}"
BACKUP_FILE="$1"
echo "[*] Creating temp directory: $TEMP_DIR"
mkdir -p "$TEMP_DIR"
# Resolve backup file path
if [ ! -f "$BACKUP_FILE" ]; then
# Try in backup directory
if [ -f "$BACKUP_DIR/$BACKUP_FILE" ]; then
BACKUP_FILE="$BACKUP_DIR/$BACKUP_FILE"
elif [ -f "$COMPOSE_DIR/$BACKUP_FILE" ]; then
BACKUP_FILE="$COMPOSE_DIR/$BACKUP_FILE"
else
print_error "Backup file not found: $1"
print_msg "Searched in:"
echo " - $1"
echo " - $BACKUP_DIR/$1"
echo " - $COMPOSE_DIR/$1"
echo ""
show_usage
fi
fi
echo "[*] Extracting backup archive..."
tar -xzf "$BACKUP_FILE" -C "$TEMP_DIR"
print_msg "Restore Script for Netbird Docker Compose"
print_msg "=========================================="
print_msg "Backup file: $BACKUP_FILE"
print_msg "Target directory: $COMPOSE_DIR"
echo ""
# ============================================
# STOP CURRENT STACK
# ============================================
echo "[*] Stopping current NetBird stack (if running)..."
docker compose down || true
# Verify backup file
if ! tar -tzf "$BACKUP_FILE" &>/dev/null; then
print_error "Invalid or corrupted backup file"
exit 1
fi
# ============================================
# RESTORE DOCKER VOLUMES
# ============================================
VOLUMES=(
"netbird_zdb_data"
"netbird_management"
"netbird_zitadel_certs"
)
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
print_msg "Backup size: $BACKUP_SIZE"
for VOL in "${VOLUMES[@]}"; do
VOL_ARCHIVE="${TEMP_DIR}/${VOL}.tar.gz"
if [[ ! -f "$VOL_ARCHIVE" ]]; then
echo "[!] WARNING: Volume archive not found for ${VOL} at ${VOL_ARCHIVE}, skipping..."
continue
# Show what will be restored
print_msg "Backup contents preview:"
tar -tzf "$BACKUP_FILE" | head -n 20
if [ $(tar -tzf "$BACKUP_FILE" | wc -l) -gt 20 ]; then
echo " ... and more files"
fi
echo ""
# Warning and confirmation
print_warning "WARNING: This will stop all services and replace current files!"
print_warning "Current directory contents will be overwritten!"
echo ""
print_question "Do you want to create a safety backup before restoring? (recommended) [Y/n]"
read -r SAFETY_BACKUP
if [[ ! "$SAFETY_BACKUP" =~ ^[Nn]$ ]]; then
SAFETY_TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
SAFETY_FILE="${BACKUP_DIR}/pre-restore-backup-${SAFETY_TIMESTAMP}.tar.gz"
print_msg "Creating safety backup: $SAFETY_FILE"
cd "$COMPOSE_DIR" || exit 1
# Stop services first if docker-compose.yml exists
if [ -f "docker-compose.yml" ]; then
print_msg "Stopping current services..."
docker-compose down 2>/dev/null
fi
echo "[*] Ensuring Docker volume exists: $VOL"
if ! docker volume ls -q | grep -q "^${VOL}$"; then
docker volume create "$VOL" >/dev/null
fi
tar -czf "$SAFETY_FILE" \
--exclude='./backup' \
--exclude='./.git' \
-C "$COMPOSE_DIR" . 2>/dev/null
echo "[*] Restoring volume: $VOL"
docker run --rm \
-v "${VOL}:/volume" \
-v "${TEMP_DIR}:/backup" \
alpine sh -c "cd /volume && tar -xzf /backup/$(basename "$VOL_ARCHIVE")"
if [ $? -eq 0 ]; then
print_msg "Safety backup created successfully"
else
print_warning "Failed to create safety backup, but continuing..."
fi
fi
echo ""
print_question "Are you sure you want to restore from this backup? [y/N]"
read -r CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
print_msg "Restore cancelled by user"
exit 0
fi
print_msg "Starting restore process..."
# Change to compose directory
cd "$COMPOSE_DIR" || {
print_error "Failed to change to directory: $COMPOSE_DIR"
exit 1
}
# Stop docker compose services if they exist
if [ -f "docker-compose.yml" ]; then
print_msg "Stopping Docker Compose services..."
docker-compose down
if [ $? -eq 0 ]; then
print_msg "Services stopped successfully"
else
print_warning "Failed to stop services (they may not be running)"
fi
else
print_msg "No docker-compose.yml found, skipping service stop"
fi
# Remove current files (except backup directory and this script)
print_msg "Removing current files..."
find "$COMPOSE_DIR" -mindepth 1 -maxdepth 1 ! -name 'backup' ! -name 'restore-netbird.sh' ! -name '.git' -exec rm -rf {} + 2>/dev/null
# Extract backup
print_msg "Extracting backup archive..."
tar -xzf "$BACKUP_FILE" -C "$COMPOSE_DIR"
if [ $? -eq 0 ]; then
print_msg "Backup extracted successfully"
else
print_error "Failed to extract backup"
exit 1
fi
# Set proper permissions
print_msg "Setting permissions..."
chmod +x "$COMPOSE_DIR"/*.sh 2>/dev/null
if [ -d "$COMPOSE_DIR/machinekey" ]; then
chmod 777 "$COMPOSE_DIR/machinekey"
fi
chmod 600 "$COMPOSE_DIR/acme.json" 2>/dev/null
# Verify critical files
print_msg "Verifying restored files..."
CRITICAL_FILES=("docker-compose.yml" ".env")
ALL_GOOD=true
for file in "${CRITICAL_FILES[@]}"; do
if [ -f "$COMPOSE_DIR/$file" ]; then
print_msg "$file restored"
else
print_error "$file missing"
ALL_GOOD=false
fi
done
# ============================================
# RESTORE CONFIG FILES
# ============================================
echo "[*] Restoring configuration files to ${BASE_DIR}..."
# docker-compose.yml
if [[ -f "${TEMP_DIR}/docker-compose.yml" ]]; then
cp -a "${TEMP_DIR}/docker-compose.yml" "${BASE_DIR}/"
if [ "$ALL_GOOD" = false ]; then
print_error "Some critical files are missing!"
exit 1
fi
# *.env files
if ls "${TEMP_DIR}"/*.env >/dev/null 2>&1; then
cp -a "${TEMP_DIR}"/*.env "${BASE_DIR}/"
# Start docker compose services
print_msg "Starting Docker Compose services..."
docker-compose up -d
if [ $? -eq 0 ]; then
print_msg "Services started successfully"
else
print_error "Failed to start services"
print_msg "You can try manually with: cd $COMPOSE_DIR && docker-compose up -d"
exit 1
fi
# management.json
if [[ -f "${TEMP_DIR}/management.json" ]]; then
cp -a "${TEMP_DIR}/management.json" "${BASE_DIR}/"
# Wait a moment and show service status
sleep 3
print_msg "Current service status:"
docker-compose ps
print_msg "=========================================="
print_msg "Restore completed successfully!"
print_msg "Restored from: $BACKUP_FILE"
if [[ ! "$SAFETY_BACKUP" =~ ^[Nn]$ ]] && [ -f "$SAFETY_FILE" ]; then
print_msg "Safety backup saved at: $SAFETY_FILE"
fi
print_msg "=========================================="
# turnserver.conf
if [[ -f "${TEMP_DIR}/turnserver.conf" ]]; then
cp -a "${TEMP_DIR}/turnserver.conf" "${BASE_DIR}/"
fi
# machinekey directory
if [[ -d "${TEMP_DIR}/machinekey" ]]; then
rm -rf "${BASE_DIR}/machinekey"
cp -a "${TEMP_DIR}/machinekey" "${BASE_DIR}/"
fi
# traefik-stack directory (if present in backup)
if [[ -d "${TEMP_DIR}/traefik-stack" ]]; then
rm -rf "${BASE_DIR}/traefik-stack"
cp -a "${TEMP_DIR}/traefik-stack" "${BASE_DIR}/"
fi
# ============================================
# CLEAN UP TEMP
# ============================================
echo "[*] Cleaning up temporary directory..."
rm -rf "$TEMP_DIR"
# ============================================
# START STACK
# ============================================
echo "[*] Starting NetBird stack..."
docker compose up -d
echo "=========================================================="
echo "Restore completed from: $BACKUP_FILE"
echo "NetBird + Zitadel stack should now be running again."
echo "=========================================================="
exit 0