From ce835ec488eaed94ed0726ca8cd3d4266ecbf9e3 Mon Sep 17 00:00:00 2001 From: Phil Date: Sat, 1 Feb 2025 15:34:17 +0000 Subject: [PATCH] Forgot to upload the script --- V2/home_assistant_backup.sh | 141 ++++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 16 deletions(-) diff --git a/V2/home_assistant_backup.sh b/V2/home_assistant_backup.sh index f3fecbe..645aed6 100644 --- a/V2/home_assistant_backup.sh +++ b/V2/home_assistant_backup.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -x +#set -x ### Global Settings ### # Set your Home Assistant SSH credentials @@ -8,9 +8,22 @@ HA_SSH_USER="SSH_USER" # Replace with your HomeAssistant server username HA_SSH_HOST="SSH_HOST_IP_OR_HOSTNAME" # Replace with your HomeAssistant server IP address HA_SSH_PORT="SSH_PORT" # Replace with your HomeAssistant server port +## Storage # Set the backup destination path -BACKUP_DEST="BACKUP_FILE_DESTINATION" # Replace with the location for the backup files +BACKUP_DEST="BACKUP_FILE_DESTINATION" # Replace with the location for the backup files +# Set the location of the Home Assistant backups (Set to default location /backup) +# If you have a custom install, using the likes of Supervised +# this location should normally be /usr/share/hassio/backup +BACKUP_FILE_LOCATION="/backup" + +# Storage threshold (in KB) for triggering cleanup +STORAGE_THRESHOLD_KB=2097152 # 2GB = 2 * 1024 * 1024 KB +# Set clean up old backups (adjust the number of days to keep) +LOCAL_BACKUP_CLEANUP="90" # Set the number of days that local backup files will be kept for (Default 90 days) +REMOTE_BACKUP_CLEANUP="30" # Set the number of days that backups on the Home Assistant server will be kept for (Default 30 days) + +## Notification Settings # ntfy settings NTFY_ENABLED=false # Set to 'true' to enable ntfy notifications NTFY_SERVER="NTFY_SERVER_FQDN_ADDRESS" # Replace with your ntfy server address @@ -20,15 +33,101 @@ NTFY_TOPIC="NTFY_TOPIC" # Replace with your ntfy topic DISCORD_ENABLED=false # Set to 'true' to enable Discord notifications DISCORD_WEBHOOK_URL="DISCORD_WEBHOOK_URL" # Replace with your Discord webhook URL -# Set clean up old backups (adjust the number of days to keep) -BACKUP_FILE_CLEANUP="90" # Set the number of days that backup files will be kept for (Default 90 days) - -# Set the location of the Home Assistant backups (Set to default location /backup) -# If you have a custom install, using the likes of Supervised -# this location should normally be /usr/share/hassio/backup -BACKUP_FILE_LOCATION="/backup" - ### Script ### +## Sanity Check## +# Function to check if the necessary variables are set and if jq and yq are installed +sanity_check() { + # Check if jq and yq are installed + if ! command -v jq &> /dev/null; then + echo "Error: jq is not installed. Please install jq before running this script." + exit 1 + fi + + if ! command -v yq &> /dev/null; then + echo "Error: yq is not installed. Please install yq before running this script." + exit 1 + fi + + # Check for each variable + if [ -z "$HA_SSH_KEY" ] || [ "$HA_SSH_KEY" == "SSH_PRIVATE_KEY" ]; then + echo "Error: SSH_PRIVATE_KEY is not set." + exit 1 + fi + + if [ -z "$HA_SSH_USER" ] || [ "$HA_SSH_USER" == "SSH_USER" ]; then + echo "Error: SSH_USER is not set." + exit 1 + fi + + if [ -z "$HA_SSH_HOST" ] || [ "$HA_SSH_HOST" == "SSH_HOST_IP_OR_HOSTNAME" ]; then + echo "Error: SSH_HOST_IP_OR_HOSTNAME is not set." + exit 1 + fi + + if [ -z "$HA_SSH_PORT" ] || [ "$HA_SSH_PORT" == "SSH_PORT" ]; then + echo "Error: SSH_PORT is not set." + exit 1 + fi + + if [ -z "$BACKUP_DEST" ] || [ "$BACKUP_DEST" == "BACKUP_FILE_DESTINATION" ]; then + echo "Error: BACKUP_FILE_DESTINATION is not set." + exit 1 + fi + + if [ "$NTFY_ENABLED" == "true" ]; then + if [ -z "$NTFY_SERVER" ] || [ "$NTFY_SERVER" == "NTFY_SERVER_FQDN_ADDRESS" ]; then + echo "Error: NTFY_SERVER_FQDN_ADDRESS is not set." + exit 1 + fi + if [ -z "$NTFY_TOPIC" ] || [ "$NTFY_TOPIC" == "NTFY_TOPIC" ]; then + echo "Error: NTFY_TOPIC is not set." + exit 1 + fi + fi + + if [ "$DISCORD_ENABLED" == "true" ]; then + if [ -z "$DISCORD_WEBHOOK_URL" ] || [ "$DISCORD_WEBHOOK_URL" == "DISCORD_WEBHOOK_URL" ]; then + echo "Error: DISCORD_WEBHOOK_URL is not set." + exit 1 + fi + fi +} + +# Call the function to check requirements and variables +sanity_check + +# Function to remove old backups from Home Assistant server (older than $REMOTE_BACKUP_CLEANUP days) +remove_old_backups_ssh() { + echo "Removing backups older than $REMOTE_BACKUP_CLEANUP days on Home Assistant server..." + + # Fetch the list of backups and parse the YAML output using yq + BACKUPS_OUTPUT=$(ssh -i "$HA_SSH_KEY" -p "$HA_SSH_PORT" "$HA_SSH_USER@$HA_SSH_HOST" "ha backups") + if ! echo "$BACKUPS_OUTPUT" | yq eval >/dev/null 2>&1; then + echo "Error: The output of 'ha backups' is not valid YAML." + return 1 + fi + + # Convert the YAML to JSON and extract old backups using jq + OLD_BACKUPS=$(echo "$BACKUPS_OUTPUT" | yq eval -o=json | jq --argjson days "$REMOTE_BACKUP_CLEANUP" -r '.backups[] | select((.date | sub("\\.[0-9]+\\+00:00$"; "Z") | fromdateiso8601) < (now - ($days * 86400))) | .slug') + + # Remove each old backup by its slug + if [ -n "$OLD_BACKUPS" ]; then + for slug in $OLD_BACKUPS; do + echo "Removing backup with slug: $slug" + ssh -i "$HA_SSH_KEY" -p "$HA_SSH_PORT" "$HA_SSH_USER@$HA_SSH_HOST" "ha backups remove $slug" + if [ $? -eq 0 ]; then + echo "Successfully removed backup with slug: $slug" + send_ntfy_notification "Old backup removed: $slug" + send_discord_notification "Old backup removed: $slug" + else + echo "Failed to remove backup with slug: $slug" + fi + done + else + echo "No old backups found to remove." + fi +} + ### Function for sending notifications ### send_ntfy_notification() { @@ -58,6 +157,16 @@ START_TIME=$(date +%s) send_ntfy_notification "Backup process started at $TIMESTAMP" send_discord_notification "Backup process started at $TIMESTAMP" +# Check available disk space on Home Assistant server +AVAILABLE_SPACE=$(ssh -i "$HA_SSH_KEY" -p "$HA_SSH_PORT" "$HA_SSH_USER@$HA_SSH_HOST" "df --output=avail / | tail -n 1") +if [ "$AVAILABLE_SPACE" -lt "$STORAGE_THRESHOLD_KB" ]; then + echo "Disk space is less than 2GB on Home Assistant server. Proceeding with remote backup cleanup..." + # Remove old backups on Home Assistant server if less than 2GB available + remove_old_backups_ssh +else + echo "Sufficient disk space available on Home Assistant server. Skipping remote backup cleanup." +fi + # Create a backup on the Home Assistant server and extract the slug BACKUP_OUTPUT=$(ssh -i "$HA_SSH_KEY" -p "$HA_SSH_PORT" "$HA_SSH_USER@$HA_SSH_HOST" "ha backup new --name=auto_backup_$TIMESTAMP") if [ $? -ne 0 ]; then @@ -104,14 +213,13 @@ if [ $? -ne 0 ]; then exit 1 fi - -# Clean up old backups if needed (adjust the number of days to keep) -find "$BACKUP_DEST" -name '*.tar' -mtime +90 -exec rm {} \; +# Clean up old backups locally (older than $LOCAL_BACKUP_CLEANUP days) +find "$BACKUP_DEST" -name '*.tar' -mtime +$LOCAL_BACKUP_CLEANUP -exec rm {} \; if [ $? -ne 0 ]; then # Send notification if cleanup fails - send_ntfy_notification "Error: Failed to clean up old backups." - send_discord_notification "Error: Failed to clean up old backups." - echo "Error: Failed to clean up old backups." + send_ntfy_notification "Error: Failed to clean up old backups locally." + send_discord_notification "Error: Failed to clean up old backups locally." + echo "Error: Failed to clean up old backups locally." exit 1 fi @@ -131,3 +239,4 @@ RUNTIME=$((END_TIME - START_TIME)) # Send notification with backup file size and script runtime send_ntfy_notification "Backup file size: $BACKUP_FILE_SIZE bytes. Script runtime: $RUNTIME seconds." send_discord_notification "Backup file size: $BACKUP_FILE_SIZE bytes. Script runtime: $RUNTIME seconds." +