150 lines
3.6 KiB
Bash
Executable File
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
|