diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..aeebef9 --- /dev/null +++ b/backup.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# --- Configuration --- +# The root directory where your docker-compose.yml and data folders are located +BACKUP_SOURCE_DIR="$(pwd)" + +# The target directory for the backup tarball (must exist on the host) +BACKUP_TARGET_DIR="$(pwd)/backup" + +# The name of the backup file (without extension) +BACKUP_NAME="mealie_backup" + +# Data volumes specified in your docker-compose.yml +DATA_VOLUMES=( + "mealie-data" + "mealie-pgdata" +) + +# Configuration file +CONFIG_FILE="docker-compose.yml" + +# --- Script Logic --- +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +TARBALL_FILENAME="${BACKUP_NAME}_${TIMESTAMP}.tar.gz" +FULL_TARBALL_PATH="${BACKUP_TARGET_DIR}/${TARBALL_FILENAME}" +TEMP_DIR="mealie_backup_content" + +echo "Starting Mealie backup at ${TIMESTAMP}..." +echo "----------------------------------------" + +# 1. 🛑 STOP CONTAINERS for Data Integrity +echo "1. Stopping Mealie services to ensure data consistency..." +# Stop the services gracefully using the docker-compose file +docker compose -f "${CONFIG_FILE}" stop mealie postgres + +if [ $? -ne 0 ]; then + echo "❌ Error: Could not stop one or more services. Aborting backup." >&2 + exit 1 +fi +echo "Services successfully stopped." +echo "---" + +# 2. Create a temporary directory to structure the backup content +echo "2. Creating temporary structure: ${TEMP_DIR}/" +mkdir -p "${TEMP_DIR}" + +# 3. Copy the configuration file and data volumes +echo " Copying configuration file: ${CONFIG_FILE}" +cp "${CONFIG_FILE}" "${TEMP_DIR}/" + +for volume in "${DATA_VOLUMES[@]}"; do + SOURCE_PATH="${BACKUP_SOURCE_DIR}/${volume}" + if [ -d "${SOURCE_PATH}" ]; then + echo " Copying data volume: ${volume}/" + # Using 'cp -r' to copy the entire data folder + cp -r "${SOURCE_PATH}" "${TEMP_DIR}/" + else + echo "Warning: Data volume ${volume} not found! Skipping." >&2 + fi +done +echo "---" + +# 4. Create the target directory and the compressed tarball +mkdir -p "${BACKUP_TARGET_DIR}" +echo "3. Creating tarball: ${FULL_TARBALL_PATH}" +tar -czf "${FULL_TARBALL_PATH}" "${TEMP_DIR}" + +# 5. Cleanup the temporary directory +echo "4. Cleaning up temporary files." +rm -rf "${TEMP_DIR}" +echo "---" + +# 6. ✅ RESTART CONTAINERS +echo "5. Restarting Mealie services with 'docker compose up -d'..." +docker compose -f "${CONFIG_FILE}" up -d mealie postgres + +if [ $? -ne 0 ]; then + echo "⚠️ Warning: Services may not have restarted correctly. Check logs manually." >&2 +else + echo "✅ Services restarted successfully." +fi +echo "---" + +# 7. Verification and final output +if [ -f "${FULL_TARBALL_PATH}" ]; then + SIZE=$(du -h "${FULL_TARBALL_PATH}" | awk '{print $1}') + echo "🎉 **Backup Successful!** File saved to: ${FULL_TARBALL_PATH} (${SIZE})" +else + echo "❌ **Backup Failed!** Tarball was not created." >&2 + exit 1 +fi \ No newline at end of file