2025-06-24 19:44:41 +02:00

150 lines
3.6 KiB
Bash
Executable File

#!/bin/bash
# Generic Service Backup Script for Docker Compose services
# Location: /home/citadel/services/paperless/backup.sh
# Runs daily at 3 AM via systemd timer
set -e
# Service Configuration
SERVICE_NAME="paperless"
SERVICE_DIR="/home/citadel/services/$SERVICE_NAME"
DATA_DIR="/home/citadel/data/$SERVICE_NAME"
TEMP_BACKUP_DIR="/tmp/$SERVICE_NAME"
CONFIG_FILE="/home/citadel/backup/restic.conf"
COMPOSE_FILE="$SERVICE_DIR/docker-compose.yml"
# Logging
LOG_FILE="/var/log/$SERVICE_NAME-backup.log"
exec 1> >(tee -a "$LOG_FILE")
exec 2> >(tee -a "$LOG_FILE" >&2)
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
cleanup() {
log "Cleaning up temporary files..."
rm -rf "$TEMP_BACKUP_DIR"
# Ensure containers are running in case of error
if docker compose -f "$COMPOSE_FILE" ps --services --filter "status=exited" | grep -q .; then
log "Some containers are stopped, restarting..."
cd "$SERVICE_DIR"
docker compose up -d
fi
}
# Set up cleanup on exit
trap cleanup EXIT
log "=== Starting $SERVICE_NAME Backup ==="
# Check if configuration exists
if [ ! -f "$CONFIG_FILE" ]; then
log "ERROR: Configuration file $CONFIG_FILE not found!"
exit 1
fi
# Source Restic configuration
source "$CONFIG_FILE"
# Create temporary backup directory
log "Creating temporary backup directory: $TEMP_BACKUP_DIR"
mkdir -p "$TEMP_BACKUP_DIR"
# Navigate to service directory
cd "$SERVICE_DIR"
# Check if compose file exists
if [ ! -f "$COMPOSE_FILE" ]; then
log "ERROR: Docker compose file $COMPOSE_FILE not found!"
exit 1
fi
log "Stopping $SERVICE_NAME containers..."
docker compose down
# Wait a moment for containers to fully stop
sleep 5
log "Creating PostgreSQL database dump..."
# Start only the database container for backup
docker compose up -d db
# Wait for database to be ready
sleep 10
# Get database credentials from .env
if [ -f "$SERVICE_DIR/.env" ]; then
source "$SERVICE_DIR/.env"
else
log "ERROR: .env file not found!"
exit 1
fi
# Create database dump
DUMP_FILE="$TEMP_BACKUP_DIR/${SERVICE_NAME}_db_$(date +%Y%m%d_%H%M%S).sql"
log "Creating database dump: $DUMP_FILE"
docker compose exec -T db pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" > "$DUMP_FILE"
if [ $? -eq 0 ]; then
log "✅ Database dump created successfully"
else
log "❌ Database dump failed!"
exit 1
fi
# Stop database container
docker compose down
log "Copying application data to temporary directory..."
# Copy data directories
cp -r "$DATA_DIR"/* "$TEMP_BACKUP_DIR/" 2>/dev/null || true
# Copy service configuration
cp -r "$SERVICE_DIR" "$TEMP_BACKUP_DIR/service_config"
log "Creating Restic backup..."
restic backup "$TEMP_BACKUP_DIR" \
--tag "$SERVICE_NAME" \
--tag "daily"
if [ $? -eq 0 ]; then
log "✅ Restic backup completed successfully with tag: $SERVICE_NAME"
else
log "❌ Restic backup failed!"
exit 1
fi
log "Restarting $SERVICE_NAME containers..."
docker compose up -d
# Wait for services to be ready
sleep 15
# Check if services are running
if docker compose ps --services --filter "status=running" | grep -q "webserver"; then
log "$SERVICE_NAME containers restarted successfully"
else
log "⚠️ Warning: Some containers may not be running properly"
fi
log "Running Restic maintenance (forget old snapshots)..."
# Keep: 7 daily, 4 weekly, 12 monthly, 2 yearly
restic forget \
--tag "$SERVICE_NAME" \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12 \
--keep-yearly 2 \
--prune
log "=== Backup completed successfully ==="
# Show backup statistics
log "Current repository stats:"
restic stats --mode raw-data